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 843f475b970..b91cdc8a1b4 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 @@ -12,6 +12,7 @@ import com.mongodb.DBObject; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Event; @@ -129,12 +130,17 @@ public interface DomainObjectFactory { RegattaLog loadRegattaLog(RegattaLikeIdentifier identifier); /** - * Loads all competitors, and resolves them via the domain factory. + * Loads all competitors and resolves them via the domain factory. */ - Collection loadAllCompetitors(); + Collection loadAllCompetitors(); /** - * Loads all boats, and resolves them via the domain factory. + * Loads all competitors with boats and resolves them via the domain factory. + */ + Collection loadAllCompetitorsWithBoat(); + + /** + * Loads all boats and resolves them via the domain factory. */ Collection loadAllBoats(); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java index 0595f886611..71dea119b70 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java @@ -7,6 +7,7 @@ import com.mongodb.DB; import com.mongodb.DBObject; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Regatta; @@ -118,9 +119,23 @@ public interface MongoObjectFactory { void storeRegattaForRaceID(String id, Regatta regatta); void removeRegattaForRaceID(String raceIDAsString, Regatta regatta); - + /** - * Stores a competitor, including the team and boat. This should not be done for competitors for which + * Stores a competitor, including the boat. This should not be done for competitors for which + * the master data is supplied by other systems, such as TracTrac, but rather for smartphone tracking, + * where this data is otherwise not recoverable. + * @param competitor the competitor to store/update in the database + */ + void storeCompetitorWithBoat(CompetitorWithBoat competitor); + + /** + * Like {@link #storeCompetitorWithBoat(CompetitorWithBoat)}, but for a collection of competitors that are all + * expected to be new, having a unique {@link Competitor#getId() ID}. + */ + void storeCompetitorsWithBoat(Iterable competitors); + + /** + * Stores a competitor. This should not be done for competitors for which * the master data is supplied by other systems, such as TracTrac, but rather for smartphone tracking, * where this data is otherwise not recoverable. * @param competitor the competitor to store/update in the database @@ -135,8 +150,12 @@ public interface MongoObjectFactory { void removeAllCompetitors(); + void removeAllCompetitorsWithBoat(); + void removeCompetitor(Competitor competitor); + void removeCompetitorWithBoat(CompetitorWithBoat competitor); + /** * Stores a boat. This should not be done for boats for which * the master data is supplied by other systems, such as TracTrac, but rather for smartphone tracking, 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 f746c06801d..b13ee1a8744 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 @@ -71,10 +71,15 @@ public enum CollectionNames { /** - * Stores competitors. + * Stores competitors with boats. */ COMPETITORS, + /** + * Stores competitors with boats. + */ + COMPETITORS_WITHOUT_BOAT, + /** * 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 7e7499b59c9..866be5c3518 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 @@ -109,6 +109,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -120,6 +121,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMa import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterEntryEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRevokeEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogSetCompetitorTimeOnTimeFactorEventImpl; @@ -224,6 +226,7 @@ import com.sap.sailing.domain.tracking.impl.WindTrackImpl; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.BoatJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.CompetitorWithBoatJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.DeviceConfigurationJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.Helpers; @@ -253,40 +256,45 @@ import com.sap.sse.util.ThreadPoolUtil; public class DomainObjectFactoryImpl implements DomainObjectFactory { private static final Logger logger = Logger.getLogger(DomainObjectFactoryImpl.class.getName()); private final CompetitorWithBoatJsonDeserializer competitorWithBoatDeserializer; + private final CompetitorJsonDeserializer competitorDeserializer; private final BoatJsonDeserializer boatDeserializer; private final DB database; - + private final DomainFactory baseDomainFactory; private final TypeBasedServiceFinderFactory serviceFinderFactory; private final TypeBasedServiceFinder deviceIdentifierServiceFinder; private final TypeBasedServiceFinder raceTrackingConnectivityParamsServiceFinder; - + /** - * Uses null as the {@link TypeBasedServiceFinder}, meaning that no {@link DeviceIdentifier}s can be loaded - * using this instance of a {@link DomainObjectFactory}. + * Uses null 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) { + + public DomainObjectFactoryImpl(DB db, DomainFactory baseDomainFactory, + TypeBasedServiceFinderFactory serviceFinderFactory) { super(); this.serviceFinderFactory = serviceFinderFactory; if (serviceFinderFactory != null) { - this.deviceIdentifierServiceFinder = serviceFinderFactory.createServiceFinder(DeviceIdentifierMongoHandler.class); + this.deviceIdentifierServiceFinder = serviceFinderFactory + .createServiceFinder(DeviceIdentifierMongoHandler.class); this.deviceIdentifierServiceFinder.setFallbackService(new PlaceHolderDeviceIdentifierMongoHandler()); - this.raceTrackingConnectivityParamsServiceFinder = serviceFinderFactory.createServiceFinder(RaceTrackingConnectivityParametersHandler.class); + this.raceTrackingConnectivityParamsServiceFinder = serviceFinderFactory + .createServiceFinder(RaceTrackingConnectivityParametersHandler.class); } else { this.deviceIdentifierServiceFinder = null; this.raceTrackingConnectivityParamsServiceFinder = null; } this.baseDomainFactory = baseDomainFactory; this.competitorWithBoatDeserializer = CompetitorWithBoatJsonDeserializer.create(baseDomainFactory); + this.competitorDeserializer = CompetitorJsonDeserializer.create(baseDomainFactory); this.boatDeserializer = BoatJsonDeserializer.create(baseDomainFactory); this.database = db; } - + @Override public DomainFactory getBaseDomainFactory() { return baseDomainFactory; @@ -307,7 +315,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return null; } } - + public static TimePoint loadTimePoint(DBObject object, String fieldName) { TimePoint result = null; Number timePointAsNumber = (Number) object.get(fieldName); @@ -320,7 +328,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { 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) { @@ -330,6 +338,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { 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}. */ @@ -372,8 +381,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { "Setting the unique index on the %s collection failed because you have too many duplicates. " + "This leads to the mongo error code %s and the following message: %s \nTo fix this follow " + "the steps provided on the wiki page: http://wiki.sapsailing.com/wiki/howto/misc/cook-book#Remove-" - + "duplicates-from-WIND_TRACK-collection", CollectionNames.WIND_TRACKS.name(), - exception.getCode(), exception.getMessage())); + + "duplicates-from-WIND_TRACK-collection", + CollectionNames.WIND_TRACKS.name(), exception.getCode(), exception.getMessage())); } else { logger.severe(String.format( "Setting the unique index on the %s collection failed with error code %s and message: %s", @@ -383,7 +392,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } @Override - public Leaderboard loadLeaderboard(String name, RegattaRegistry regattaRegistry, LeaderboardRegistry leaderboardRegistry) { + public Leaderboard loadLeaderboard(String name, RegattaRegistry regattaRegistry, + LeaderboardRegistry leaderboardRegistry) { DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); Leaderboard result = null; try { @@ -394,7 +404,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } } catch (Exception e) { // something went wrong during DB access; report, then use empty new wind track - logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load leaderboard "+name+"."); + logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load leaderboard " + name + "."); logger.log(Level.SEVERE, "loadLeaderboard", e); } return result; @@ -405,12 +415,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { String leaderboardName, String wrappedRegattaLeaderboardName, LeaderboardRegistry leaderboardRegistry) { final RegattaLeaderboardWithEliminations result; BasicDBList eliminatedCompetitorIds = (BasicDBList) dbLeaderboard.get(FieldNames.ELMINATED_COMPETITORS.name()); - result = new DelegatingRegattaLeaderboardWithCompetitorElimination(()-> - (RegattaLeaderboard) leaderboardRegistry.getLeaderboardByName(wrappedRegattaLeaderboardName), leaderboardName); + result = new DelegatingRegattaLeaderboardWithCompetitorElimination( + () -> (RegattaLeaderboard) leaderboardRegistry.getLeaderboardByName(wrappedRegattaLeaderboardName), + leaderboardName); for (Object eliminatedCompetitorId : eliminatedCompetitorIds) { - Competitor eliminatedCompetitor = baseDomainFactory.getCompetitorStore().getExistingCompetitorById((Serializable) eliminatedCompetitorId); + Competitor eliminatedCompetitor = baseDomainFactory.getCompetitorStore() + .getExistingCompetitorById((Serializable) eliminatedCompetitorId); if (eliminatedCompetitor == null) { - logger.warning("Couldn't find eliminated competitor with ID "+eliminatedCompetitorId); + logger.warning("Couldn't find eliminated competitor with ID " + eliminatedCompetitorId); } else { result.setEliminated(eliminatedCompetitor, true); } @@ -438,25 +450,29 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { * {@link RegattaLeaderboard} cannot be found; the leaderboard loaded or found in * leaderboardRegistry, otherwise */ - private Leaderboard loadLeaderboard(DBObject dbLeaderboard, RegattaRegistry regattaRegistry, LeaderboardRegistry leaderboardRegistry, - LeaderboardGroup groupForMetaLeaderboard) { + private Leaderboard loadLeaderboard(DBObject dbLeaderboard, RegattaRegistry regattaRegistry, + LeaderboardRegistry leaderboardRegistry, LeaderboardGroup groupForMetaLeaderboard) { Leaderboard result = null; String leaderboardName = (String) dbLeaderboard.get(FieldNames.LEADERBOARD_NAME.name()); if (leaderboardRegistry != null) { result = leaderboardRegistry.getLeaderboardByName(leaderboardName); } if (result == null) { - String wrappedRegattaLeaderboardName = (String) dbLeaderboard.get(FieldNames.WRAPPED_REGATTA_LEADERBOARD_NAME.name()); + String wrappedRegattaLeaderboardName = (String) dbLeaderboard + .get(FieldNames.WRAPPED_REGATTA_LEADERBOARD_NAME.name()); if (wrappedRegattaLeaderboardName != null) { - result = loadRegattaLeaderboardWithEliminations(dbLeaderboard, leaderboardName, wrappedRegattaLeaderboardName, leaderboardRegistry); + result = loadRegattaLeaderboardWithEliminations(dbLeaderboard, leaderboardName, + wrappedRegattaLeaderboardName, leaderboardRegistry); } else { if (groupForMetaLeaderboard != null) { result = new LeaderboardGroupMetaLeaderboard(groupForMetaLeaderboard, - loadScoringScheme(dbLeaderboard), loadResultDiscardingRule(dbLeaderboard, FieldNames.LEADERBOARD_DISCARDING_THRESHOLDS)); + loadScoringScheme(dbLeaderboard), + loadResultDiscardingRule(dbLeaderboard, FieldNames.LEADERBOARD_DISCARDING_THRESHOLDS)); groupForMetaLeaderboard.setOverallLeaderboard(result); } else { String regattaName = (String) dbLeaderboard.get(FieldNames.REGATTA_NAME.name()); - ThresholdBasedResultDiscardingRule resultDiscardingRule = loadResultDiscardingRule(dbLeaderboard, FieldNames.LEADERBOARD_DISCARDING_THRESHOLDS); + ThresholdBasedResultDiscardingRule resultDiscardingRule = loadResultDiscardingRule(dbLeaderboard, + FieldNames.LEADERBOARD_DISCARDING_THRESHOLDS); if (regattaName == null) { result = loadFlexibleLeaderboard(dbLeaderboard, resultDiscardingRule); } else { @@ -465,8 +481,10 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } } if (result != null) { - DelayedLeaderboardCorrections loadedLeaderboardCorrections = new DelayedLeaderboardCorrectionsImpl(result, baseDomainFactory); - loadLeaderboardCorrections(dbLeaderboard, loadedLeaderboardCorrections, result.getScoreCorrection()); + DelayedLeaderboardCorrections loadedLeaderboardCorrections = new DelayedLeaderboardCorrectionsImpl( + result, baseDomainFactory); + loadLeaderboardCorrections(dbLeaderboard, loadedLeaderboardCorrections, + result.getScoreCorrection()); loadSuppressedCompetitors(dbLeaderboard, loadedLeaderboardCorrections); loadColumnFactors(dbLeaderboard, result); } @@ -477,7 +495,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { // add the leaderboard to the registry if (leaderboardRegistry != null) { leaderboardRegistry.addLeaderboard(result); - logger.info("loaded leaderboard "+result.getName()+" into "+leaderboardRegistry); + logger.info("loaded leaderboard " + result.getName() + " into " + leaderboardRegistry); } } } @@ -494,15 +512,18 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { if (raceColumn != null) { raceColumn.setFactor(factor); } else { - logger.warning("Expected to find race column named "+raceColumnName+" in leaderboard "+result.getName()+ - " to apply column factor "+factor+", but the race column wasn't found. Ignoring factor."); + logger.warning("Expected to find race column named " + raceColumnName + " in leaderboard " + + result.getName() + " to apply column factor " + factor + + ", but the race column wasn't found. Ignoring factor."); } } } } - private void loadSuppressedCompetitors(DBObject dbLeaderboard, DelayedLeaderboardCorrections loadedLeaderboardCorrections) { - BasicDBList dbSuppressedCompetitorIDs = (BasicDBList) dbLeaderboard.get(FieldNames.LEADERBOARD_SUPPRESSED_COMPETITOR_IDS.name()); + private void loadSuppressedCompetitors(DBObject dbLeaderboard, + DelayedLeaderboardCorrections loadedLeaderboardCorrections) { + BasicDBList dbSuppressedCompetitorIDs = (BasicDBList) dbLeaderboard + .get(FieldNames.LEADERBOARD_SUPPRESSED_COMPETITOR_IDS.name()); if (dbSuppressedCompetitorIDs != null) { for (Object competitorId : dbSuppressedCompetitorIDs) { loadedLeaderboardCorrections.suppressCompetitorByID((Serializable) competitorId); @@ -511,7 +532,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } /** - * @param dbObject expects to find a field identified by field which holds a {@link BasicDBList} + * @param dbObject + * expects to find a field identified by field which holds a {@link BasicDBList} */ private ThresholdBasedResultDiscardingRule loadResultDiscardingRule(DBObject dbObject, FieldNames field) { BasicDBList dbDiscardIndexResultsStartingWithHowManyRaces = (BasicDBList) dbObject.get(field.name()); @@ -533,27 +555,30 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { /** * @return null if the regatta cannot be resolved; otherwise the leaderboard for the regatta specified */ - private RegattaLeaderboard loadRegattaLeaderboard(String leaderboardName, String regattaName, DBObject dbLeaderboard, - ThresholdBasedResultDiscardingRule resultDiscardingRule, RegattaRegistry regattaRegistry) { + private RegattaLeaderboard loadRegattaLeaderboard(String leaderboardName, String regattaName, + DBObject dbLeaderboard, ThresholdBasedResultDiscardingRule resultDiscardingRule, + RegattaRegistry regattaRegistry) { RegattaLeaderboard result = null; Regatta regatta = regattaRegistry.getRegatta(new RegattaName(regattaName)); if (regatta == null) { - logger.info("Couldn't find regatta "+regattaName+" for corresponding regatta leaderboard. Not loading regatta leaderboard."); + logger.info("Couldn't find regatta " + regattaName + + " for corresponding regatta leaderboard. Not loading regatta leaderboard."); } else { result = new RegattaLeaderboardImpl(regatta, resultDiscardingRule); - result.setName(leaderboardName); // this will temporarily set the display name; it will be adjusted later if a display name is found + result.setName(leaderboardName); // this will temporarily set the display name; it will be adjusted later if + // a display name is found } return result; } - + private RaceLogStore getRaceLogStore() { - return MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore( - new MongoObjectFactoryImpl(database, serviceFinderFactory), this); + return MongoRaceLogStoreFactory.INSTANCE + .getMongoRaceLogStore(new MongoObjectFactoryImpl(database, serviceFinderFactory), this); } - + private RegattaLogStore getRegattaLogStore() { - return MongoRegattaLogStoreFactory.INSTANCE.getMongoRegattaLogStore( - new MongoObjectFactoryImpl(database, serviceFinderFactory), this); + return MongoRegattaLogStoreFactory.INSTANCE + .getMongoRegattaLogStore(new MongoObjectFactoryImpl(database, serviceFinderFactory), this); } private FlexibleLeaderboard loadFlexibleLeaderboard(DBObject dbLeaderboard, @@ -563,21 +588,21 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { if (dbRaceColumns == null) { // this was probably an orphaned overall leaderboard logger.warning("Probably found orphan overall leaderboard named " - + dbLeaderboard.get(FieldNames.LEADERBOARD_NAME.name())+". Ignoring."); + + dbLeaderboard.get(FieldNames.LEADERBOARD_NAME.name()) + ". Ignoring."); result = null; } else { final ScoringScheme scoringScheme = loadScoringScheme(dbLeaderboard); - + Serializable courseAreaId = (Serializable) dbLeaderboard.get(FieldNames.COURSE_AREA_ID.name()); CourseArea courseArea = null; if (courseAreaId != null) { UUID courseAreaUuid = UUID.fromString(courseAreaId.toString()); courseArea = baseDomainFactory.getExistingCourseAreaById(courseAreaUuid); } - + result = new FlexibleLeaderboardImpl(getRaceLogStore(), getRegattaLogStore(), - (String) dbLeaderboard.get(FieldNames.LEADERBOARD_NAME.name()), - resultDiscardingRule, scoringScheme, courseArea); + (String) dbLeaderboard.get(FieldNames.LEADERBOARD_NAME.name()), resultDiscardingRule, scoringScheme, + courseArea); // For a FlexibleLeaderboard, there should be only the default fleet for any race column for (Object dbRaceColumnAsObject : dbRaceColumns) { BasicDBObject dbRaceColumn = (BasicDBObject) dbRaceColumnAsObject; @@ -618,11 +643,13 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { private void loadLeaderboardCorrections(DBObject dbLeaderboard, DelayedLeaderboardCorrections correctionsToUpdate, SettableScoreCorrection scoreCorrectionToUpdate) { - BasicDBList carriedPointsById = (BasicDBList) dbLeaderboard.get(FieldNames.LEADERBOARD_CARRIED_POINTS_BY_ID.name()); + BasicDBList carriedPointsById = (BasicDBList) dbLeaderboard + .get(FieldNames.LEADERBOARD_CARRIED_POINTS_BY_ID.name()); if (carriedPointsById != null) { for (Object o : carriedPointsById) { DBObject competitorIdAndCarriedPoints = (DBObject) o; - Serializable competitorId = (Serializable) competitorIdAndCarriedPoints.get(FieldNames.COMPETITOR_ID.name()); + Serializable competitorId = (Serializable) competitorIdAndCarriedPoints + .get(FieldNames.COMPETITOR_ID.name()); Double carriedPointsForCompetitor = ((Number) competitorIdAndCarriedPoints .get(FieldNames.LEADERBOARD_CARRIED_POINTS.name())).doubleValue(); if (carriedPointsForCompetitor != null) { @@ -632,20 +659,22 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } DBObject dbScoreCorrection = (DBObject) dbLeaderboard.get(FieldNames.LEADERBOARD_SCORE_CORRECTIONS.name()); if (dbScoreCorrection.containsField(FieldNames.LEADERBOARD_SCORE_CORRECTION_TIMESTAMP.name())) { - scoreCorrectionToUpdate.setTimePointOfLastCorrectionsValidity( - new MillisecondsTimePoint((Long) dbScoreCorrection.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_TIMESTAMP.name()))); + scoreCorrectionToUpdate.setTimePointOfLastCorrectionsValidity(new MillisecondsTimePoint( + (Long) dbScoreCorrection.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_TIMESTAMP.name()))); dbScoreCorrection.removeField(FieldNames.LEADERBOARD_SCORE_CORRECTION_TIMESTAMP.name()); } if (dbScoreCorrection.containsField(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name())) { - scoreCorrectionToUpdate.setComment((String) dbScoreCorrection.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name())); + scoreCorrectionToUpdate + .setComment((String) dbScoreCorrection.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name())); dbScoreCorrection.removeField(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name()); } for (String escapedRaceColumnName : dbScoreCorrection.keySet()) { // deprecated style: a DBObject per race where the keys are the escaped competitor names // new style: a BasicDBList per race where each entry is a DBObject with COMPETITOR_ID and - // LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON and LEADERBOARD_CORRECTED_SCORE fields each + // LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON and LEADERBOARD_CORRECTED_SCORE fields each DBObject dbScoreCorrectionForRace = (DBObject) dbScoreCorrection.get(escapedRaceColumnName); - final RaceColumn raceColumn = correctionsToUpdate.getLeaderboard().getRaceColumnByName(MongoUtils.unescapeDollarAndDot(escapedRaceColumnName)); + final RaceColumn raceColumn = correctionsToUpdate.getLeaderboard() + .getRaceColumnByName(MongoUtils.unescapeDollarAndDot(escapedRaceColumnName)); if (raceColumn != null) { for (Object o : (BasicDBList) dbScoreCorrectionForRace) { DBObject dbScoreCorrectionForCompetitorInRace = (DBObject) o; @@ -653,12 +682,12 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { .get(FieldNames.COMPETITOR_ID.name()); if (dbScoreCorrectionForCompetitorInRace .containsField(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name())) { - correctionsToUpdate.setMaxPointsReasonByID(competitorId, raceColumn, MaxPointsReason - .valueOf((String) dbScoreCorrectionForCompetitorInRace + correctionsToUpdate.setMaxPointsReasonByID(competitorId, raceColumn, + MaxPointsReason.valueOf((String) dbScoreCorrectionForCompetitorInRace .get(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name()))); } - if (dbScoreCorrectionForCompetitorInRace.containsField(FieldNames.LEADERBOARD_CORRECTED_SCORE - .name())) { + if (dbScoreCorrectionForCompetitorInRace + .containsField(FieldNames.LEADERBOARD_CORRECTED_SCORE.name())) { final Double leaderboardCorrectedScore = ((Number) dbScoreCorrectionForCompetitorInRace .get(FieldNames.LEADERBOARD_CORRECTED_SCORE.name())).doubleValue(); correctionsToUpdate.correctScoreByID(competitorId, raceColumn, @@ -670,22 +699,25 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { + " in leaderboard " + correctionsToUpdate.getLeaderboard().getName()); } } - DBObject competitorDisplayNames = (DBObject) dbLeaderboard.get(FieldNames.LEADERBOARD_COMPETITOR_DISPLAY_NAMES.name()); + DBObject competitorDisplayNames = (DBObject) dbLeaderboard + .get(FieldNames.LEADERBOARD_COMPETITOR_DISPLAY_NAMES.name()); // deprecated style: a DBObject whose keys are the escaped competitor names // new style: a BasicDBList whose entries are DBObjects with COMPETITOR_ID and COMPETITOR_DISPLAY_NAME fields if (competitorDisplayNames != null) { if (competitorDisplayNames instanceof BasicDBList) { for (Object o : (BasicDBList) competitorDisplayNames) { DBObject competitorDisplayName = (DBObject) o; - final Serializable competitorId = (Serializable) competitorDisplayName.get(FieldNames.COMPETITOR_ID.name()); - final String displayName = (String) competitorDisplayName.get(FieldNames.COMPETITOR_DISPLAY_NAME.name()); + final Serializable competitorId = (Serializable) competitorDisplayName + .get(FieldNames.COMPETITOR_ID.name()); + final String displayName = (String) competitorDisplayName + .get(FieldNames.COMPETITOR_DISPLAY_NAME.name()); correctionsToUpdate.setDisplayNameByID(competitorId, displayName); } } else { - logger.severe("Deprecated, now unreadable format of the "+FieldNames.LEADERBOARD_COMPETITOR_DISPLAY_NAMES.name() - +" field for leaderboard "+dbLeaderboard.get(FieldNames.LEADERBOARD_NAME.name())+ - ". You will have to update the competitor display names manually: "+ - competitorDisplayNames); + logger.severe("Deprecated, now unreadable format of the " + + FieldNames.LEADERBOARD_COMPETITOR_DISPLAY_NAMES.name() + " field for leaderboard " + + dbLeaderboard.get(FieldNames.LEADERBOARD_NAME.name()) + + ". You will have to update the competitor display names manually: " + competitorDisplayNames); } } } @@ -719,15 +751,17 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } @Override - public LeaderboardGroup loadLeaderboardGroup(String name, RegattaRegistry regattaRegistry, LeaderboardRegistry leaderboardRegistry) { + public LeaderboardGroup loadLeaderboardGroup(String name, RegattaRegistry regattaRegistry, + LeaderboardRegistry leaderboardRegistry) { DBCollection leaderboardGroupCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()); LeaderboardGroup leaderboardGroup = null; try { BasicDBObject query = new BasicDBObject(); query.put(FieldNames.LEADERBOARD_GROUP_NAME.name(), name); - leaderboardGroup = loadLeaderboardGroup(leaderboardGroupCollection.findOne(query), regattaRegistry, leaderboardRegistry); + leaderboardGroup = loadLeaderboardGroup(leaderboardGroupCollection.findOne(query), regattaRegistry, + leaderboardRegistry); } catch (Exception e) { - logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load leaderboard group "+name+"."); + logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load leaderboard group " + name + "."); logger.log(Level.SEVERE, "loadLeaderboardGroup", e); } @@ -735,7 +769,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } @Override - public Iterable getAllLeaderboardGroups(RegattaRegistry regattaRegistry, LeaderboardRegistry leaderboardRegistry) { + public Iterable getAllLeaderboardGroups(RegattaRegistry regattaRegistry, + LeaderboardRegistry leaderboardRegistry) { DBCollection leaderboardGroupCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()); Set leaderboardGroups = new HashSet(); try { @@ -744,8 +779,10 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { final LeaderboardGroup leaderboardGroup = loadLeaderboardGroup(o, regattaRegistry, leaderboardRegistry); leaderboardGroups.add(leaderboardGroup); if (!hasUUID) { - // in an effort to migrate leaderboard groups without ID to such that have a UUID as their ID, we need - // to write a leaderboard group to the database again after it just received a UUID for the first time: + // in an effort to migrate leaderboard groups without ID to such that have a UUID as their ID, we + // need + // to write a leaderboard group to the database again after it just received a UUID for the first + // time: logger.info("Existing LeaderboardGroup " + leaderboardGroup.getName() + " received a UUID during migration; updating the leaderboard group in the database"); new MongoObjectFactoryImpl(database).storeLeaderboardGroup(leaderboardGroup); @@ -759,21 +796,22 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return leaderboardGroups; } - private LeaderboardGroup loadLeaderboardGroup(DBObject o, RegattaRegistry regattaRegistry, LeaderboardRegistry leaderboardRegistry) { + private LeaderboardGroup loadLeaderboardGroup(DBObject o, RegattaRegistry regattaRegistry, + LeaderboardRegistry leaderboardRegistry) { DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); String name = (String) o.get(FieldNames.LEADERBOARD_GROUP_NAME.name()); UUID uuid = (UUID) o.get(FieldNames.LEADERBOARD_GROUP_UUID.name()); if (uuid == null) { uuid = UUID.randomUUID(); - logger.info("Leaderboard group "+name+" receives UUID "+uuid+" in a migration effort"); + logger.info("Leaderboard group " + name + " receives UUID " + uuid + " in a migration effort"); // migration: leaderboard groups that don't yet have a UUID receive a random one } String description = (String) o.get(FieldNames.LEADERBOARD_GROUP_DESCRIPTION.name()); String displayName = (String) o.get(FieldNames.LEADERBOARD_GROUP_DISPLAY_NAME.name()); - boolean displayGroupsInReverseOrder = false; // default value + boolean displayGroupsInReverseOrder = false; // default value Object displayGroupsInReverseOrderObj = o.get(FieldNames.LEADERBOARD_GROUP_DISPLAY_IN_REVERSE_ORDER.name()); if (displayGroupsInReverseOrderObj != null) { - displayGroupsInReverseOrder = (Boolean) displayGroupsInReverseOrderObj; + displayGroupsInReverseOrder = (Boolean) displayGroupsInReverseOrderObj; } ArrayList leaderboards = new ArrayList(); BasicDBList dbLeaderboardIds = (BasicDBList) o.get(FieldNames.LEADERBOARD_GROUP_LEADERBOARDS.name()); @@ -787,11 +825,13 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { leaderboards.add(loadedLeaderboard); } } else { - logger.warning("couldn't find leaderboard with ID "+dbLeaderboardId+" referenced by leaderboard group "+name); + logger.warning("couldn't find leaderboard with ID " + dbLeaderboardId + + " referenced by leaderboard group " + name); } } - logger.info("loaded leaderboard group "+name); - LeaderboardGroupImpl result = new LeaderboardGroupImpl(uuid, name, description, displayName, displayGroupsInReverseOrder, leaderboards); + logger.info("loaded leaderboard group " + name); + LeaderboardGroupImpl result = new LeaderboardGroupImpl(uuid, name, description, displayName, + displayGroupsInReverseOrder, leaderboards); Object overallLeaderboardIdOrName = o.get(FieldNames.LEADERBOARD_GROUP_OVERALL_LEADERBOARD.name()); if (overallLeaderboardIdOrName != null) { final DBObject dbOverallLeaderboard; @@ -803,40 +843,50 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { if (dbOverallLeaderboard != null) { // the loadLeaderboard call adds the overall leaderboard to the leaderboard registry and sets it as the // overall leaderboard of the leaderboard group - loadLeaderboard(dbOverallLeaderboard, regattaRegistry, leaderboardRegistry, /* groupForMetaLeaderboard */ result); + loadLeaderboard(dbOverallLeaderboard, regattaRegistry, leaderboardRegistry, + /* groupForMetaLeaderboard */ result); } } return result; } @Override - public Iterable getLeaderboardsNotInGroup(RegattaRegistry regattaRegistry, LeaderboardRegistry leaderboardRegistry) { + public Iterable getLeaderboardsNotInGroup(RegattaRegistry regattaRegistry, + LeaderboardRegistry leaderboardRegistry) { DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); Set result = new HashSet(); try { // For MongoDB 2.4 $where with refs to global objects no longer works // http://docs.mongodb.org/manual/reference/operator/where/#op._S_where // Also a single where leads to a table walk without using indexes. So avoid $where. - + // Don't change the query object, unless you know what you're doing. // It queries all leaderboards not referenced to be part of a leaderboard group // and in particular not being an overall leaderboard of a leaderboard group. DBCursor allLeaderboards = leaderboardCollection.find(); for (DBObject leaderboardFromDB : allLeaderboards) { DBObject inLeaderboardGroupsQuery = new BasicDBObject(); - inLeaderboardGroupsQuery.put(FieldNames.LEADERBOARD_GROUP_LEADERBOARDS.name(), ((ObjectId)leaderboardFromDB.get("_id")).toString()); - boolean inLeaderboardGroups = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()).find(inLeaderboardGroupsQuery).size()>0; + inLeaderboardGroupsQuery.put(FieldNames.LEADERBOARD_GROUP_LEADERBOARDS.name(), + ((ObjectId) leaderboardFromDB.get("_id")).toString()); + boolean inLeaderboardGroups = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()) + .find(inLeaderboardGroupsQuery).size() > 0; DBObject inLeaderboardGroupOverallQuery = new BasicDBObject(); - inLeaderboardGroupOverallQuery.put(FieldNames.LEADERBOARD_GROUP_OVERALL_LEADERBOARD.name(), ((ObjectId)leaderboardFromDB.get("_id")).toString()); - boolean inLeaderboardGroupOverall = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()).find(inLeaderboardGroupOverallQuery).size()>0; - + inLeaderboardGroupOverallQuery.put(FieldNames.LEADERBOARD_GROUP_OVERALL_LEADERBOARD.name(), + ((ObjectId) leaderboardFromDB.get("_id")).toString()); + boolean inLeaderboardGroupOverall = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()) + .find(inLeaderboardGroupOverallQuery).size() > 0; + DBObject inLeaderboardGroupOverallQueryName = new BasicDBObject(); - inLeaderboardGroupOverallQueryName.put(FieldNames.LEADERBOARD_GROUP_OVERALL_LEADERBOARD.name(), leaderboardFromDB.get(FieldNames.LEADERBOARD_NAME.name())); - boolean inLeaderboardGroupOverallName = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()).find(inLeaderboardGroupOverallQueryName).size()>0; - + inLeaderboardGroupOverallQueryName.put(FieldNames.LEADERBOARD_GROUP_OVERALL_LEADERBOARD.name(), + leaderboardFromDB.get(FieldNames.LEADERBOARD_NAME.name())); + boolean inLeaderboardGroupOverallName = database + .getCollection(CollectionNames.LEADERBOARD_GROUPS.name()) + .find(inLeaderboardGroupOverallQueryName).size() > 0; + if (!inLeaderboardGroups && !inLeaderboardGroupOverall && !inLeaderboardGroupOverallName) { - final Leaderboard loadedLeaderboard = loadLeaderboard(leaderboardFromDB, regattaRegistry, leaderboardRegistry, /* groupForMetaLeaderboard */ null); + final Leaderboard loadedLeaderboard = loadLeaderboard(leaderboardFromDB, regattaRegistry, + leaderboardRegistry, /* groupForMetaLeaderboard */ null); if (loadedLeaderboard != null) { result.add(loadedLeaderboard); } @@ -850,16 +900,18 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } @Override - public WindTrack loadWindTrack(String regattaName, RaceDefinition race, WindSource windSource, long millisecondsOverWhichToAverage) { + public WindTrack loadWindTrack(String regattaName, RaceDefinition race, WindSource windSource, + long millisecondsOverWhichToAverage) { final WindTrack result; - Map resultMap = loadWindTracks(regattaName, race, windSource, millisecondsOverWhichToAverage); + Map resultMap = loadWindTracks(regattaName, race, windSource, + millisecondsOverWhichToAverage); if (resultMap.containsKey(windSource)) { result = resultMap.get(windSource); } else { // create an empty wind track as result if no fixes were found in store for the wind source requested result = new WindTrackImpl(millisecondsOverWhichToAverage, windSource.getType().getBaseConfidence(), - windSource.getType().useSpeed(), - /* nameForReadWriteLock */ WindTrackImpl.class.getSimpleName()+" for source "+windSource.toString()); + windSource.getType().useSpeed(), /* nameForReadWriteLock */ WindTrackImpl.class.getSimpleName() + + " for source " + windSource.toString()); } return result; } @@ -867,7 +919,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { @Override public Map loadWindTracks(String regattaName, RaceDefinition race, long millisecondsOverWhichToAverageWind) { - Map result = loadWindTracks(regattaName, race, /* constrain wind source */ null, millisecondsOverWhichToAverageWind); + Map result = loadWindTracks(regattaName, race, /* constrain wind source */ null, + millisecondsOverWhichToAverageWind); return result; } @@ -891,7 +944,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { for (DBObject dbWind : windTracks.find(queryById)) { loadWindFix(result, dbWind, millisecondsOverWhichToAverageWind); } - // Additionally check for legacy wind fixes stored with the old EVENT_NAME key; if any are found, migrate them + // Additionally check for legacy wind fixes stored with the old EVENT_NAME key; if any are found, migrate + // them BasicDBObject queryByName = new BasicDBObject(); queryByName.put(FieldNames.EVENT_NAME.name(), regattaName); queryByName.put(FieldNames.RACE_NAME.name(), race.getName()); @@ -907,35 +961,39 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { windFixesToMigrate.add(new MongoObjectFactoryImpl(database).storeWindTrackEntry(race, regattaName, wind.getB(), wind.getA())); } - logger.info("Migrating "+windFixesFoundByName.size()+" wind fixes of regatta "+regattaName+ - " and race "+race.getName()+" to ID-based keys"); + logger.info("Migrating " + windFixesFoundByName.size() + " wind fixes of regatta " + regattaName + + " and race " + race.getName() + " to ID-based keys"); windTracks.insert(windFixesToMigrate.toArray(new DBObject[windFixesToMigrate.size()])); - logger.info("Removing "+windFixesFoundByName.size()+" wind fixes that were keyed by the names of regatta "+regattaName+ - " and race "+race.getName()); + logger.info("Removing " + windFixesFoundByName.size() + + " wind fixes that were keyed by the names of regatta " + regattaName + " and race " + + race.getName()); windTracks.remove(queryByName); } } catch (Exception e) { // something went wrong during DB access; report, then use empty new wind track - logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load recorded wind data. Check MongoDB settings."); + logger.log(Level.SEVERE, + "Error connecting to MongoDB, unable to load recorded wind data. Check MongoDB settings."); logger.log(Level.SEVERE, "loadWindTrack", e); } return result; } - private Util.Pair loadWindFix(Map result, DBObject dbWind, long millisecondsOverWhichToAverageWind) { + private Util.Pair loadWindFix(Map result, DBObject dbWind, + long millisecondsOverWhichToAverageWind) { Wind wind = loadWind((DBObject) dbWind.get(FieldNames.WIND.name())); WindSourceType windSourceType = WindSourceType.valueOf((String) dbWind.get(FieldNames.WIND_SOURCE_NAME.name())); WindSource windSource; if (dbWind.containsField(FieldNames.WIND_SOURCE_ID.name())) { - windSource = new WindSourceWithAdditionalID(windSourceType, (String) dbWind.get(FieldNames.WIND_SOURCE_ID.name())); + windSource = new WindSourceWithAdditionalID(windSourceType, + (String) dbWind.get(FieldNames.WIND_SOURCE_ID.name())); } else { windSource = new WindSourceImpl(windSourceType); } WindTrack track = result.get(windSource); if (track == null) { track = new WindTrackImpl(millisecondsOverWhichToAverageWind, windSource.getType().getBaseConfidence(), - windSource.getType().useSpeed(), - /* nameForReadWriteLock */ WindTrackImpl.class.getSimpleName()+" for source "+windSource.toString()); + windSource.getType().useSpeed(), /* nameForReadWriteLock */ WindTrackImpl.class.getSimpleName() + + " for source " + windSource.toString()); result.put(windSource, track); } track.add(wind); @@ -951,12 +1009,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { UUID eventId = (UUID) dbLink.get(FieldNames.EVENT_ID.name()); Event event = eventResolver.getEvent(eventId); if (event == null) { - logger.info("Found leaderboard group IDs for event with ID "+eventId+" but couldn't find that event."); + logger.info( + "Found leaderboard group IDs for event with ID " + eventId + " but couldn't find that event."); } else { @SuppressWarnings("unchecked") List leaderboardGroupIDs = (List) dbLink.get(FieldNames.LEADERBOARD_GROUP_UUID.name()); for (UUID leaderboardGroupID : leaderboardGroupIDs) { - LeaderboardGroup leaderboardGroup = leaderboardGroupResolver.getLeaderboardGroupByID(leaderboardGroupID); + LeaderboardGroup leaderboardGroup = leaderboardGroupResolver + .getLeaderboardGroupByID(leaderboardGroupID); if (leaderboardGroup != null) { event.addLeaderboardGroup(leaderboardGroup); } @@ -1018,7 +1078,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { boolean isStandaloneServer = (Boolean) serverDBObject.get(FieldNames.SERVER_IS_STANDALONE.name()); return new SailingServerConfigurationImpl(isStandaloneServer); } - + private RemoteSailingServerReference loadRemoteSailingSever(DBObject serverDBObject) { RemoteSailingServerReference result = null; String name = (String) serverDBObject.get(FieldNames.SERVER_NAME.name()); @@ -1050,8 +1110,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } /** - * An event doesn't store its regattas; it's the regatta that stores a reference to its event; the regatta - * needs to add itself to the event when loaded or instantiated. + * An event doesn't store its regattas; it's the regatta that stores a reference to its event; the regatta needs to + * add itself to the event when loaded or instantiated. */ private Event loadEvent(DBObject eventDBObject) { String name = (String) eventDBObject.get(FieldNames.EVENT_NAME.name()); @@ -1059,7 +1119,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { UUID id = (UUID) eventDBObject.get(FieldNames.EVENT_ID.name()); TimePoint startDate = loadTimePoint(eventDBObject, FieldNames.EVENT_START_DATE); TimePoint endDate = loadTimePoint(eventDBObject, FieldNames.EVENT_END_DATE); - boolean isPublic = eventDBObject.get(FieldNames.EVENT_IS_PUBLIC.name()) != null ? (Boolean) eventDBObject.get(FieldNames.EVENT_IS_PUBLIC.name()) : false; + boolean isPublic = eventDBObject.get(FieldNames.EVENT_IS_PUBLIC.name()) != null + ? (Boolean) eventDBObject.get(FieldNames.EVENT_IS_PUBLIC.name()) : false; Venue venue = loadVenue((DBObject) eventDBObject.get(FieldNames.VENUE.name())); Event result = new EventImpl(name, startDate, endDate, venue, isPublic, id); result.setDescription(description); @@ -1068,7 +1129,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { try { result.setOfficialWebsiteURL(new URL(officialWebSiteURLAsString)); } catch (MalformedURLException e) { - logger.severe("Error parsing official website URL "+officialWebSiteURLAsString+" for event "+name+". Ignoring this URL."); + logger.severe("Error parsing official website URL " + officialWebSiteURLAsString + " for event " + name + + ". Ignoring this URL."); } } String baseURLAsString = (String) eventDBObject.get(FieldNames.EVENT_BASE_URL.name()); @@ -1076,7 +1138,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { try { result.setBaseURL(new URL(baseURLAsString)); } catch (MalformedURLException e) { - logger.severe("Error parsing base URL "+baseURLAsString+" for event "+name+". Ignoring this URL."); + logger.severe( + "Error parsing base URL " + baseURLAsString + " for event " + name + ". Ignoring this URL."); } } BasicDBList images = (BasicDBList) eventDBObject.get(FieldNames.EVENT_IMAGES.name()); @@ -1097,14 +1160,15 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } } } - BasicDBList sailorsInfoWebsiteURLs = (BasicDBList) eventDBObject.get(FieldNames.EVENT_SAILORS_INFO_WEBSITES.name()); + BasicDBList sailorsInfoWebsiteURLs = (BasicDBList) eventDBObject + .get(FieldNames.EVENT_SAILORS_INFO_WEBSITES.name()); if (sailorsInfoWebsiteURLs != null) { for (Object sailorsInfoWebsiteObject : sailorsInfoWebsiteURLs) { DBObject sailorsInfoWebsiteDBObject = (DBObject) sailorsInfoWebsiteObject; URL url = loadURL(sailorsInfoWebsiteDBObject, FieldNames.SAILORS_INFO_URL); String localeRaw = (String) sailorsInfoWebsiteDBObject.get(FieldNames.SAILORS_INFO_LOCALE.name()); if (url != null) { - Locale locale = localeRaw != null ? Locale.forLanguageTag(localeRaw) : null; + Locale locale = localeRaw != null ? Locale.forLanguageTag(localeRaw) : null; result.setSailorsInfoWebsiteURL(locale, url); } } @@ -1162,7 +1226,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } BoatClass boatClass = null; if (boatClassName != null) { - boolean typicallyStartsUpwind = (Boolean) dbRegatta.get(FieldNames.BOAT_CLASS_TYPICALLY_STARTS_UPWIND.name()); + boolean typicallyStartsUpwind = (Boolean) dbRegatta + .get(FieldNames.BOAT_CLASS_TYPICALLY_STARTS_UPWIND.name()); boatClass = baseDomainFactory.getOrCreateBoatClass(boatClassName, typicallyStartsUpwind); } BasicDBList dbSeries = (BasicDBList) dbRegatta.get(FieldNames.REGATTA_SERIES.name()); @@ -1176,30 +1241,39 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { RegattaConfiguration configuration = null; if (dbRegatta.containsField(FieldNames.REGATTA_REGATTA_CONFIGURATION.name())) { try { - JSONObject json = Helpers.toJSONObjectSafe(new JSONParser().parse(JSON.serialize(dbRegatta.get(FieldNames.REGATTA_REGATTA_CONFIGURATION.name())))); + JSONObject json = Helpers.toJSONObjectSafe(new JSONParser() + .parse(JSON.serialize(dbRegatta.get(FieldNames.REGATTA_REGATTA_CONFIGURATION.name())))); configuration = RegattaConfigurationJsonDeserializer.create().deserialize(json); - } catch (JsonDeserializationException|ParseException e) { + } catch (JsonDeserializationException | ParseException e) { logger.log(Level.WARNING, "Error loading racing procedure configration for regatta.", e); } } - final Double buoyZoneRadiusInHullLengths = (Double) dbRegatta.get(FieldNames.REGATTA_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS.name()); - final Boolean useStartTimeInference = (Boolean) dbRegatta.get(FieldNames.REGATTA_USE_START_TIME_INFERENCE.name()); - final Boolean controlTrackingFromStartAndFinishTimes = (Boolean) dbRegatta.get(FieldNames.REGATTA_CONTROL_TRACKING_FROM_START_AND_FINISH_TIMES.name()); - Boolean canBoatsOfCompetitorsChangePerRace = (Boolean) dbRegatta.get(FieldNames.REGATTA_CAN_BOATS_OF_COMPETITORS_CHANGE_PER_RACE.name()); + final Double buoyZoneRadiusInHullLengths = (Double) dbRegatta + .get(FieldNames.REGATTA_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS.name()); + final Boolean useStartTimeInference = (Boolean) dbRegatta + .get(FieldNames.REGATTA_USE_START_TIME_INFERENCE.name()); + final Boolean controlTrackingFromStartAndFinishTimes = (Boolean) dbRegatta + .get(FieldNames.REGATTA_CONTROL_TRACKING_FROM_START_AND_FINISH_TIMES.name()); + Boolean canBoatsOfCompetitorsChangePerRace = (Boolean) dbRegatta + .get(FieldNames.REGATTA_CAN_BOATS_OF_COMPETITORS_CHANGE_PER_RACE.name()); // for backward compatibility - if(canBoatsOfCompetitorsChangePerRace == null) { + if (canBoatsOfCompetitorsChangePerRace == null) { canBoatsOfCompetitorsChangePerRace = false; } 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); + 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; } - + private RankingMetricConstructor loadRankingMetricConstructor(DBObject dbRegatta) { DBObject rankingMetricJson = (DBObject) dbRegatta.get(FieldNames.REGATTA_RANKING_METRIC.name()); // default is OneDesignRankingMetric @@ -1207,7 +1281,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { if (rankingMetricJson == null) { result = OneDesignRankingMetric::new; } else { - final String rankingMetricTypeName = (String) rankingMetricJson.get(FieldNames.REGATTA_RANKING_METRIC_TYPE.name()); + final String rankingMetricTypeName = (String) rankingMetricJson + .get(FieldNames.REGATTA_RANKING_METRIC_TYPE.name()); result = RankingMetricsFactory.getRankingMetricConstructor(RankingMetrics.valueOf(rankingMetricTypeName)); } return result; @@ -1225,7 +1300,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { // can happen that the database contains a scoring scheme that // has not yet been implemented - fall back with a warning scoringSchemeType = ScoringSchemeType.LOW_POINT; - logger.warning("Could not find scoring scheme " + scoringSchemeTypeName + "! Most probably this has not yet been implemented or even been removed."); + logger.warning("Could not find scoring scheme " + scoringSchemeTypeName + + "! Most probably this has not yet been implemented or even been removed."); } } return scoringSchemeType; @@ -1250,17 +1326,22 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { if (isFleetCanRunInParallelObject != null) { isFleetsCanRunInParallel = (Boolean) dbSeries.get(FieldNames.SERIES_IS_FLEETS_CAN_RUN_IN_PARALLEL.name()); } - final Integer maximumNumberOfDiscards = (Integer) dbSeries.get(FieldNames.SERIES_MAXIMUM_NUMBER_OF_DISCARDS.name()); + final Integer maximumNumberOfDiscards = (Integer) dbSeries + .get(FieldNames.SERIES_MAXIMUM_NUMBER_OF_DISCARDS.name()); Boolean startsWithZeroScore = (Boolean) dbSeries.get(FieldNames.SERIES_STARTS_WITH_ZERO_SCORE.name()); - Boolean hasSplitFleetContiguousScoring = (Boolean) dbSeries.get(FieldNames.SERIES_HAS_SPLIT_FLEET_CONTIGUOUS_SCORING.name()); - Boolean firstColumnIsNonDiscardableCarryForward = (Boolean) dbSeries.get(FieldNames.SERIES_STARTS_WITH_NON_DISCARDABLE_CARRY_FORWARD.name()); + Boolean hasSplitFleetContiguousScoring = (Boolean) dbSeries + .get(FieldNames.SERIES_HAS_SPLIT_FLEET_CONTIGUOUS_SCORING.name()); + Boolean firstColumnIsNonDiscardableCarryForward = (Boolean) dbSeries + .get(FieldNames.SERIES_STARTS_WITH_NON_DISCARDABLE_CARRY_FORWARD.name()); final BasicDBList dbFleets = (BasicDBList) dbSeries.get(FieldNames.SERIES_FLEETS.name()); List fleets = loadFleets(dbFleets); BasicDBList dbRaceColumns = (BasicDBList) dbSeries.get(FieldNames.SERIES_RACE_COLUMNS.name()); Iterable raceColumnNames = loadRaceColumnNames(dbRaceColumns); - Series series = new SeriesImpl(name, isMedal, isFleetsCanRunInParallel, fleets, raceColumnNames, trackedRegattaRegistry); + Series series = new SeriesImpl(name, isMedal, isFleetsCanRunInParallel, fleets, raceColumnNames, + trackedRegattaRegistry); if (dbSeries.get(FieldNames.SERIES_DISCARDING_THRESHOLDS.name()) != null) { - ThresholdBasedResultDiscardingRule resultDiscardingRule = loadResultDiscardingRule(dbSeries, FieldNames.SERIES_DISCARDING_THRESHOLDS); + ThresholdBasedResultDiscardingRule resultDiscardingRule = loadResultDiscardingRule(dbSeries, + FieldNames.SERIES_DISCARDING_THRESHOLDS); series.setResultDiscardingRule(resultDiscardingRule); } if (startsWithZeroScore != null) { @@ -1323,7 +1404,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { Color color = null; if (colorAsInt != null) { int r = colorAsInt % 256; - int g = (colorAsInt / 256 ) % 256; + int g = (colorAsInt / 256) % 256; int b = (colorAsInt / 256 / 256) % 256; color = new RGBColor(r, g, b); } @@ -1356,7 +1437,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { loadRaceLogEvents(result, query); } catch (Throwable t) { // something went wrong during DB access; report, then use empty new race log - logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load recorded race log data. Check MongoDB settings."); + logger.log(Level.SEVERE, + "Error connecting to MongoDB, unable to load recorded race log data. Check MongoDB settings."); logger.log(Level.SEVERE, "loadRaceLog", t); } return result; @@ -1373,12 +1455,12 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { result.add(raceLogEvent); } } catch (IllegalStateException e) { - logger.log(Level.SEVERE, "Couldn't load race log event "+o+": "+e.getMessage(), e); + logger.log(Level.SEVERE, "Couldn't load race log event " + o + ": " + e.getMessage(), e); } } return result; } - + public RaceLogEvent loadRaceLogEvent(DBObject dbObject) { TimePoint logicalTimePoint = loadTimePoint(dbObject); TimePoint createdAt = loadTimePoint(dbObject, FieldNames.RACE_LOG_EVENT_CREATED_AT); @@ -1399,11 +1481,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { if (eventClass.equals(RaceLogStartTimeEvent.class.getSimpleName())) { return loadRaceLogStartTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogStartOfTrackingEvent.class.getSimpleName())) { - return loadRaceLogStartOfTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogStartOfTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogEndOfTrackingEvent.class.getSimpleName())) { - return loadRaceLogEndOfTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogEndOfTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogDependentStartTimeEvent.class.getSimpleName())) { - return loadRaceLogDependentStartTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogDependentStartTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogRaceStatusEvent.class.getSimpleName())) { return loadRaceLogRaceStatusEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogFlagEvent.class.getSimpleName())) { @@ -1411,119 +1496,152 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } else if (eventClass.equals(RaceLogPassChangeEvent.class.getSimpleName())) { return loadRaceLogPassChangeEvent(createdAt, author, logicalTimePoint, id, passId, competitors); } else if (eventClass.equals(RaceLogCourseAreaChangedEvent.class.getSimpleName())) { - return loadRaceLogCourseAreaChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogCourseAreaChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogCourseDesignChangedEvent.class.getSimpleName())) { - return loadRaceLogCourseDesignChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogCourseDesignChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogFinishPositioningListChangedEvent.class.getSimpleName())) { - return loadRaceLogFinishPositioningListChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogFinishPositioningListChangedEvent(createdAt, author, logicalTimePoint, id, passId, + competitors, dbObject); } else if (eventClass.equals(RaceLogFinishPositioningConfirmedEvent.class.getSimpleName())) { - return loadRaceLogFinishPositioningConfirmedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogFinishPositioningConfirmedEvent(createdAt, author, logicalTimePoint, id, passId, + competitors, dbObject); } else if (eventClass.equals(RaceLogPathfinderEvent.class.getSimpleName())) { return loadRaceLogPathfinderEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogGateLineOpeningTimeEvent.class.getSimpleName())) { - return loadRaceLogGateLineOpeningTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogGateLineOpeningTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogStartProcedureChangedEvent.class.getSimpleName())) { - return loadRaceLogStartProcedureChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogStartProcedureChangedEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogProtestStartTimeEvent.class.getSimpleName())) { - return loadRaceLogProtestStartTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogProtestStartTimeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogWindFixEvent.class.getSimpleName())) { return loadRaceLogWindFixEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogDenoteForTrackingEvent.class.getSimpleName())) { - return loadRaceLogDenoteForTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogDenoteForTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogStartTrackingEvent.class.getSimpleName())) { - return loadRaceLogStartTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogStartTrackingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogRevokeEvent.class.getSimpleName())) { return loadRaceLogRevokeEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); } else if (eventClass.equals(RaceLogRegisterCompetitorEvent.class.getSimpleName())) { - return loadRaceLogRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); } else if (eventClass.equals(RaceLogRegisterCompetitorAndBoatEvent.class.getSimpleName())) { - return loadRaceLogRegisterCompetitorAndBoatEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogRegisterCompetitorAndBoatEvent(createdAt, author, logicalTimePoint, id, passId, + competitors, dbObject); } else if (eventClass.equals(RaceLogAdditionalScoringInformationEvent.class.getSimpleName())) { - return loadRaceLogAdditionalScoringInformationEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); - } else if (eventClass.equals(RaceLogFixedMarkPassingEvent.class.getSimpleName())){ - return loadRaceLogFixedMarkPassingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); - } else if (eventClass.equals(RaceLogSuppressedMarkPassingsEvent.class.getSimpleName())){ - return loadRaceLogSuppressedMarkPassingsEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); - } else if (eventClass.equals(RaceLogUseCompetitorsFromRaceLogEvent.class.getSimpleName())){ - return loadRaceLogUseCompetitorsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); - } else if (eventClass.equals(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.class.getSimpleName())){ - return loadRaceLogUseCompetitorsAndBoatsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, competitors, dbObject); + return loadRaceLogAdditionalScoringInformationEvent(createdAt, author, logicalTimePoint, id, passId, + competitors, dbObject); + } else if (eventClass.equals(RaceLogFixedMarkPassingEvent.class.getSimpleName())) { + return loadRaceLogFixedMarkPassingEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); + } else if (eventClass.equals(RaceLogSuppressedMarkPassingsEvent.class.getSimpleName())) { + return loadRaceLogSuppressedMarkPassingsEvent(createdAt, author, logicalTimePoint, id, passId, competitors, + dbObject); + } else if (eventClass.equals(RaceLogUseCompetitorsFromRaceLogEvent.class.getSimpleName())) { + return loadRaceLogUseCompetitorsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, + competitors, dbObject); + } else if (eventClass.equals(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.class.getSimpleName())) { + return loadRaceLogUseCompetitorsAndBoatsFromRaceLogEvent(createdAt, author, logicalTimePoint, id, passId, + competitors, dbObject); } throw new IllegalStateException(String.format("Unknown RaceLogEvent type %s", eventClass)); } private RaceLogEvent loadRaceLogUseCompetitorsFromRaceLogEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { return new RaceLogUseCompetitorsFromRaceLogEventImpl(createdAt, author, logicalTimePoint, id, passId); } - private RaceLogEvent loadRaceLogUseCompetitorsAndBoatsFromRaceLogEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogEvent loadRaceLogUseCompetitorsAndBoatsFromRaceLogEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, + List competitors, DBObject dbObject) { return new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(createdAt, author, logicalTimePoint, id, passId); } - private RaceLogEvent loadRaceLogWindFixEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogEvent loadRaceLogWindFixEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { Wind wind = loadWind((DBObject) dbObject.get(FieldNames.WIND.name())); Boolean isMagnetic = (Boolean) dbObject.get(FieldNames.IS_MAGNETIC.name()); - return new RaceLogWindFixEventImpl(createdAt, logicalTimePoint, author, id, passId, wind, isMagnetic == null ? true : isMagnetic); + return new RaceLogWindFixEventImpl(createdAt, logicalTimePoint, author, id, passId, wind, + isMagnetic == null ? true : isMagnetic); } - private RaceLogEvent loadRaceLogDenoteForTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogEvent loadRaceLogDenoteForTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { String raceName = (String) dbObject.get(FieldNames.RACE_NAME.name()); - BoatClass boatClass = baseDomainFactory.getOrCreateBoatClass((String) dbObject.get(FieldNames.BOAT_CLASS_NAME.name())); + BoatClass boatClass = baseDomainFactory + .getOrCreateBoatClass((String) dbObject.get(FieldNames.BOAT_CLASS_NAME.name())); Serializable raceId = (Serializable) dbObject.get(FieldNames.RACE_ID.name()); - return new RaceLogDenoteForTrackingEventImpl(createdAt, logicalTimePoint, author, id, passId, raceName, boatClass, raceId); + return new RaceLogDenoteForTrackingEventImpl(createdAt, logicalTimePoint, author, id, passId, raceName, + boatClass, raceId); } - private RaceLogEvent loadRaceLogStartTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogEvent loadRaceLogStartTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { return new RaceLogStartTrackingEventImpl(createdAt, logicalTimePoint, author, id, passId); } - private RaceLogEvent loadRaceLogRevokeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { - Serializable revokedEventId = Helpers.tryUuidConversion( - (Serializable) dbObject.get(FieldNames.RACE_LOG_REVOKED_EVENT_ID.name())); + private RaceLogEvent loadRaceLogRevokeEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { + Serializable revokedEventId = Helpers + .tryUuidConversion((Serializable) dbObject.get(FieldNames.RACE_LOG_REVOKED_EVENT_ID.name())); String revokedEventType = (String) dbObject.get(FieldNames.RACE_LOG_REVOKED_EVENT_TYPE.name()); String revokedEventShortInfo = (String) dbObject.get(FieldNames.RACE_LOG_REVOKED_EVENT_SHORT_INFO.name()); String reason = (String) dbObject.get(FieldNames.RACE_LOG_REVOKED_REASON.name()); - return new RaceLogRevokeEventImpl(createdAt, logicalTimePoint, author, id, passId, - revokedEventId, revokedEventType, revokedEventShortInfo, reason); + return new RaceLogRevokeEventImpl(createdAt, logicalTimePoint, author, id, passId, revokedEventId, + revokedEventType, revokedEventShortInfo, reason); } - private RaceLogEvent loadRaceLogRegisterCompetitorEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { - Serializable competitorId = (Serializable) dbObject.get(FieldNames.RACE_LOG_COMPETITOR_ID.name()); - Competitor comp = baseDomainFactory.getCompetitorStore().getExistingCompetitorById(competitorId); + private RaceLogEvent loadRaceLogRegisterCompetitorEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { + Serializable competitorId = (Serializable) dbObject.get(FieldNames.RACE_LOG_COMPETITOR_ID.name()); + CompetitorWithBoat comp = baseDomainFactory.getCompetitorStore().getExistingCompetitorWithBoatById(competitorId); return new RaceLogRegisterCompetitorEventImpl(createdAt, logicalTimePoint, author, id, passId, comp); } - private RaceLogEvent loadRaceLogRegisterCompetitorAndBoatEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogEvent loadRaceLogRegisterCompetitorAndBoatEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { Serializable competitorId = (Serializable) dbObject.get(FieldNames.RACE_LOG_COMPETITOR_ID.name()); Serializable boatId = (Serializable) dbObject.get(FieldNames.RACE_LOG_BOAT_ID.name()); Competitor comp = baseDomainFactory.getCompetitorStore().getExistingCompetitorById(competitorId); Boat boat = baseDomainFactory.getCompetitorStore().getExistingBoatById(boatId); - return new RaceLogRegisterCompetitorAndBoatEventImpl(createdAt, logicalTimePoint, author, id, passId, comp, boat); + return new RaceLogRegisterCompetitorAndBoatEventImpl(createdAt, logicalTimePoint, author, id, passId, comp, + boat); } - private RaceLogEvent loadRaceLogAdditionalScoringInformationEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { - Object additionalScoringInformationTypeInfo = dbObject.get(FieldNames.RACE_LOG_ADDITIONAL_SCORING_INFORMATION_TYPE.name()); + private RaceLogEvent loadRaceLogAdditionalScoringInformationEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, + List competitors, DBObject dbObject) { + Object additionalScoringInformationTypeInfo = dbObject + .get(FieldNames.RACE_LOG_ADDITIONAL_SCORING_INFORMATION_TYPE.name()); AdditionalScoringInformationType informationType = AdditionalScoringInformationType.UNKNOWN; if (additionalScoringInformationTypeInfo != null) { informationType = AdditionalScoringInformationType.valueOf(additionalScoringInformationTypeInfo.toString()); } else { - logger.warning("Could not find additional scoring information attached to db log for " + dbObject.toString()); + logger.warning( + "Could not find additional scoring information attached to db log for " + dbObject.toString()); } - return new RaceLogAdditionalScoringInformationEventImpl(createdAt, logicalTimePoint, author, id, passId, informationType); + return new RaceLogAdditionalScoringInformationEventImpl(createdAt, logicalTimePoint, author, id, passId, + informationType); } private RaceLogEvent loadRaceLogProtestStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { TimePoint protestStartTime = loadTimePoint(dbObject, FieldNames.RACE_LOG_PROTEST_START_TIME); TimePoint protestEndTime = loadTimePoint(dbObject, FieldNames.RACE_LOG_PROTEST_END_TIME); if (protestEndTime == null) { @@ -1535,78 +1653,101 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } private RaceLogEvent loadRaceLogStartProcedureChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { - RacingProcedureType type = RacingProcedureType.valueOf(dbObject.get(FieldNames.RACE_LOG_START_PROCEDURE_TYPE.name()).toString()); + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { + RacingProcedureType type = RacingProcedureType + .valueOf(dbObject.get(FieldNames.RACE_LOG_START_PROCEDURE_TYPE.name()).toString()); return new RaceLogStartProcedureChangedEventImpl(createdAt, logicalTimePoint, author, id, passId, type); } - private RaceLogEvent loadRaceLogGateLineOpeningTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogEvent loadRaceLogGateLineOpeningTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { Number gateLaunchStopTime = (Number) dbObject.get(FieldNames.RACE_LOG_GATE_LINE_OPENING_TIME.name()); Number golfDownTime = 0; if (dbObject.containsField(FieldNames.RACE_LOG_GOLF_DOWN_TIME.name())) { golfDownTime = (Number) dbObject.get(FieldNames.RACE_LOG_GOLF_DOWN_TIME.name()); } - return new RaceLogGateLineOpeningTimeEventImpl(createdAt, logicalTimePoint, author, id, - passId, gateLaunchStopTime == null ? null : gateLaunchStopTime.longValue(), golfDownTime.longValue()); + return new RaceLogGateLineOpeningTimeEventImpl(createdAt, logicalTimePoint, author, id, passId, + gateLaunchStopTime == null ? null : gateLaunchStopTime.longValue(), golfDownTime.longValue()); } - - private RaceLogEvent loadRaceLogPathfinderEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { + + private RaceLogEvent loadRaceLogPathfinderEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { String pathfinderId = dbObject.get(FieldNames.RACE_LOG_PATHFINDER_ID.name()).toString(); return new RaceLogPathfinderEventImpl(createdAt, logicalTimePoint, author, id, passId, pathfinderId); } - + private RaceLogEvent loadRaceLogFinishPositioningConfirmedEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { - BasicDBList dbPositionedCompetitorList = (BasicDBList) dbObject.get(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name()); + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { + BasicDBList dbPositionedCompetitorList = (BasicDBList) dbObject + .get(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name()); CompetitorResults positionedCompetitors = null; - //When a confirmation event is loaded that does not contain the positioned competitors (this is the case for the ESS events in - //Singapore and Quingdao) then null should be set for the positionedCompetitors, which is evaluated later on. + // When a confirmation event is loaded that does not contain the positioned competitors (this is the case for + // the ESS events in + // Singapore and Quingdao) then null should be set for the positionedCompetitors, which is evaluated later on. if (dbPositionedCompetitorList != null) { positionedCompetitors = loadPositionedCompetitors(dbPositionedCompetitorList); } - - return new RaceLogFinishPositioningConfirmedEventImpl(createdAt, logicalTimePoint, author, id, passId, positionedCompetitors); + + return new RaceLogFinishPositioningConfirmedEventImpl(createdAt, logicalTimePoint, author, id, passId, + positionedCompetitors); } - private RaceLogEvent loadRaceLogFinishPositioningListChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { - BasicDBList dbPositionedCompetitorList = (BasicDBList) dbObject.get(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name()); + private RaceLogEvent loadRaceLogFinishPositioningListChangedEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, + List competitors, DBObject dbObject) { + BasicDBList dbPositionedCompetitorList = (BasicDBList) dbObject + .get(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name()); CompetitorResults positionedCompetitors = loadPositionedCompetitors(dbPositionedCompetitorList); - - return new RaceLogFinishPositioningListChangedEventImpl(createdAt, logicalTimePoint, author, id, passId, positionedCompetitors); + + return new RaceLogFinishPositioningListChangedEventImpl(createdAt, logicalTimePoint, author, id, passId, + positionedCompetitors); } - private RaceLogEvent loadRaceLogPassChangeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors) { + private RaceLogEvent loadRaceLogPassChangeEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors) { return new RaceLogPassChangeEventImpl(createdAt, logicalTimePoint, author, id, passId); } - private RaceLogCourseDesignChangedEvent loadRaceLogCourseDesignChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogCourseDesignChangedEvent loadRaceLogCourseDesignChangedEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, + List competitors, DBObject dbObject) { String courseName = (String) dbObject.get(FieldNames.RACE_LOG_COURSE_DESIGN_NAME.name()); - CourseBase courseData = loadCourseData((BasicDBList) dbObject.get(FieldNames.RACE_LOG_COURSE_DESIGN.name()), courseName); + CourseBase courseData = loadCourseData((BasicDBList) dbObject.get(FieldNames.RACE_LOG_COURSE_DESIGN.name()), + courseName); final String courseDesignerModeName = (String) dbObject.get(FieldNames.RACE_LOG_COURSE_DESIGNER_MODE.name()); - final CourseDesignerMode courseDesignerMode = courseDesignerModeName == null ? null : CourseDesignerMode.valueOf(courseDesignerModeName); - return new RaceLogCourseDesignChangedEventImpl(createdAt, logicalTimePoint, author, id, passId, courseData, courseDesignerMode); + final CourseDesignerMode courseDesignerMode = courseDesignerModeName == null ? null + : CourseDesignerMode.valueOf(courseDesignerModeName); + return new RaceLogCourseDesignChangedEventImpl(createdAt, logicalTimePoint, author, id, passId, courseData, + courseDesignerMode); } - private RaceLogCourseAreaChangedEvent loadRaceLogCourseAreaChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogCourseAreaChangedEvent loadRaceLogCourseAreaChangedEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, + List competitors, DBObject dbObject) { Serializable courseAreaId = (Serializable) dbObject.get(FieldNames.COURSE_AREA_ID.name()); return new RaceLogCourseAreaChangeEventImpl(createdAt, logicalTimePoint, author, id, passId, courseAreaId); } - - private RaceLogEvent loadRaceLogFixedMarkPassingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { + + private RaceLogEvent loadRaceLogFixedMarkPassingEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { TimePoint ofFixedPassing = loadTimePoint(dbObject, FieldNames.TIMEPOINT_OF_FIXED_MARKPASSING); Integer zeroBasedIndexOfWaypoint = (Integer) dbObject.get(FieldNames.INDEX_OF_PASSED_WAYPOINT.name()); - return new RaceLogFixedMarkPassingEventImpl(createdAt, logicalTimePoint, author, id, competitors, passId, ofFixedPassing, zeroBasedIndexOfWaypoint); + return new RaceLogFixedMarkPassingEventImpl(createdAt, logicalTimePoint, author, id, competitors, passId, + ofFixedPassing, zeroBasedIndexOfWaypoint); } - private RaceLogEvent loadRaceLogSuppressedMarkPassingsEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, Integer passId, List competitors, DBObject dbObject) { - Integer zeroBasedIndexOfFirstSuppressedWaypoint = (Integer) dbObject.get(FieldNames.INDEX_OF_FIRST_SUPPRESSED_WAYPOINT.name()); - return new RaceLogSuppressedMarkPassingsEventImpl(createdAt, logicalTimePoint, author, id, competitors, passId, zeroBasedIndexOfFirstSuppressedWaypoint); + private RaceLogEvent loadRaceLogSuppressedMarkPassingsEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { + Integer zeroBasedIndexOfFirstSuppressedWaypoint = (Integer) dbObject + .get(FieldNames.INDEX_OF_FIRST_SUPPRESSED_WAYPOINT.name()); + return new RaceLogSuppressedMarkPassingsEventImpl(createdAt, logicalTimePoint, author, id, competitors, passId, + zeroBasedIndexOfFirstSuppressedWaypoint); } private CompetitorResults loadPositionedCompetitors(BasicDBList dbPositionedCompetitorList) { @@ -1616,22 +1757,29 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { DBObject dbObject = (DBObject) object; final Serializable competitorId = (Serializable) dbObject.get(FieldNames.COMPETITOR_ID.name()); String competitorDisplayName = (String) dbObject.get(FieldNames.COMPETITOR_DISPLAY_NAME.name()); - //The Competitor name is a new field in the list. Therefore the name might be null for existing events. In this case a standard name is set. + // The Competitor name is a new field in the list. Therefore the name might be null for existing events. In + // this case a standard name is set. if (competitorDisplayName == null) { competitorDisplayName = "loaded competitor"; } - //At this point we do not retrieve the competitor object since at any point in time, especially after a server restart, the DomainFactory and its competitor - //cache might be empty. But at this time the race log is loaded from database, so the competitor would be null. - //By not using the Competitor object retrieved from the DomainFactory we get completely independent from server restarts and the timepoint of loading - //competitors by tracking providers. + // At this point we do not retrieve the competitor object since at any point in time, especially after a + // server restart, the DomainFactory and its competitor + // cache might be empty. But at this time the race log is loaded from database, so the competitor would be + // null. + // By not using the Competitor object retrieved from the DomainFactory we get completely independent from + // server restarts and the timepoint of loading + // competitors by tracking providers. final Integer rank = (Integer) dbObject.get(FieldNames.LEADERBOARD_RANK.name()); - final MaxPointsReason maxPointsReason = MaxPointsReason.valueOf((String) dbObject.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name())); + final MaxPointsReason maxPointsReason = MaxPointsReason + .valueOf((String) dbObject.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name())); final Double score = (Double) dbObject.get(FieldNames.LEADERBOARD_CORRECTED_SCORE.name()); - final Long finishingTimePointAsMillis = (Long) dbObject.get(FieldNames.RACE_LOG_FINISHING_TIME_AS_MILLIS.name()); - final TimePoint finishingTime = finishingTimePointAsMillis == null ? null : new MillisecondsTimePoint(finishingTimePointAsMillis); + final Long finishingTimePointAsMillis = (Long) dbObject + .get(FieldNames.RACE_LOG_FINISHING_TIME_AS_MILLIS.name()); + final TimePoint finishingTime = finishingTimePointAsMillis == null ? null + : new MillisecondsTimePoint(finishingTimePointAsMillis); final String comment = (String) dbObject.get(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name()); - CompetitorResultImpl positionedCompetitor = new CompetitorResultImpl( - competitorId, competitorDisplayName, rank == null ? rankCounter : rank, maxPointsReason, score, finishingTime, comment); + CompetitorResultImpl positionedCompetitor = new CompetitorResultImpl(competitorId, competitorDisplayName, + rank == null ? rankCounter : rank, maxPointsReason, score, finishingTime, comment); positionedCompetitors.add(positionedCompetitor); rankCounter++; } @@ -1648,7 +1796,9 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return competitors; } - private RaceLogFlagEvent loadRaceLogFlagEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogFlagEvent loadRaceLogFlagEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { Flags upperFlag = Flags.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_FLAG_UPPER.name())); Flags lowerFlag = Flags.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_FLAG_LOWER.name())); Boolean displayed = Boolean.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_FLAG_DISPLAYED.name())); @@ -1657,41 +1807,56 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return null; } - return new RaceLogFlagEventImpl(createdAt, logicalTimePoint, author, id, passId, upperFlag, lowerFlag, displayed); + return new RaceLogFlagEventImpl(createdAt, logicalTimePoint, author, id, passId, upperFlag, lowerFlag, + displayed); } - private RaceLogStartTimeEvent loadRaceLogStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogStartTimeEvent loadRaceLogStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { TimePoint startTime = loadTimePoint(dbObject, FieldNames.RACE_LOG_EVENT_START_TIME); - RaceLogRaceStatus nextStatus = RaceLogRaceStatus.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name())); + RaceLogRaceStatus nextStatus = RaceLogRaceStatus + .valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name())); return new RaceLogStartTimeEventImpl(createdAt, logicalTimePoint, author, id, passId, startTime, nextStatus); } - private RaceLogStartOfTrackingEvent loadRaceLogStartOfTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogStartOfTrackingEvent loadRaceLogStartOfTrackingEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, + List competitors, DBObject dbObject) { return new RaceLogStartOfTrackingEventImpl(createdAt, logicalTimePoint, author, id, passId); } - private RaceLogEndOfTrackingEvent loadRaceLogEndOfTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogEndOfTrackingEvent loadRaceLogEndOfTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { return new RaceLogEndOfTrackingEventImpl(createdAt, logicalTimePoint, author, id, passId); } - private RaceLogDependentStartTimeEvent loadRaceLogDependentStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { + private RaceLogDependentStartTimeEvent loadRaceLogDependentStartTimeEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, + List competitors, DBObject dbObject) { final Object regattaLikeNameObject = dbObject.get(FieldNames.RACE_LOG_DEPDENDENT_ON_REGATTALIKE.name()); final String regattaLikeName = regattaLikeNameObject == null ? null : regattaLikeNameObject.toString(); final Object raceColumnNameObject = dbObject.get(FieldNames.RACE_LOG_DEPDENDENT_ON_RACECOLUMN.name()); final String raceColumnName = raceColumnNameObject == null ? null : raceColumnNameObject.toString(); final Object fleetNameObject = dbObject.get(FieldNames.RACE_LOG_DEPDENDENT_ON_FLEET.name()); final String fleetName = fleetNameObject == null ? null : fleetNameObject.toString(); - final SimpleRaceLogIdentifier dependentRaceLog = new SimpleRaceLogIdentifierImpl(regattaLikeName, raceColumnName, fleetName); + final SimpleRaceLogIdentifier dependentRaceLog = new SimpleRaceLogIdentifierImpl(regattaLikeName, + raceColumnName, fleetName); final Object startTimeDifferenceObject = dbObject.get(FieldNames.RACE_LOG_START_TIME_DIFFERENCE_IN_MS.name()); - final Duration startTimeDifference = startTimeDifferenceObject == null ? null : - new MillisecondsDurationImpl(((Number) startTimeDifferenceObject).longValue()); - RaceLogRaceStatus nextStatus = RaceLogRaceStatus.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name())); - return new RaceLogDependentStartTimeEventImpl(createdAt, logicalTimePoint, author, id, - passId, dependentRaceLog, startTimeDifference, nextStatus); + final Duration startTimeDifference = startTimeDifferenceObject == null ? null + : new MillisecondsDurationImpl(((Number) startTimeDifferenceObject).longValue()); + RaceLogRaceStatus nextStatus = RaceLogRaceStatus + .valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name())); + return new RaceLogDependentStartTimeEventImpl(createdAt, logicalTimePoint, author, id, passId, dependentRaceLog, + startTimeDifference, nextStatus); } - private RaceLogRaceStatusEvent loadRaceLogRaceStatusEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { - RaceLogRaceStatus nextStatus = RaceLogRaceStatus.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name())); + private RaceLogRaceStatusEvent loadRaceLogRaceStatusEvent(TimePoint createdAt, AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, + DBObject dbObject) { + RaceLogRaceStatus nextStatus = RaceLogRaceStatus + .valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name())); return new RaceLogRaceStatusEventImpl(createdAt, logicalTimePoint, author, id, passId, nextStatus); } @@ -1705,12 +1870,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { loadRegattaLogEvents(result, query, identifier); } catch (Throwable t) { // something went wrong during DB access; report, then use empty new regatta log - logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load recorded regatta log data for "+identifier+". Check MongoDB settings.", t); + logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load recorded regatta log data for " + + identifier + ". Check MongoDB settings.", t); } return result; } - private void loadRegattaLogEvents(RegattaLog targetRegattaLog, BasicDBObject query, RegattaLikeIdentifier regattaLogIdentifier) { + private void loadRegattaLogEvents(RegattaLog targetRegattaLog, BasicDBObject query, + RegattaLikeIdentifier regattaLogIdentifier) { DBCollection collection = database.getCollection(CollectionNames.REGATTA_LOGS.name()); for (DBObject o : collection.find(query)) { try { @@ -1719,7 +1886,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { targetRegattaLog.load(event); } } catch (IllegalStateException e) { - logger.log(Level.SEVERE, "Couldn't load regatta log event "+o+": "+e.getMessage(), e); + logger.log(Level.SEVERE, "Couldn't load regatta log event " + o + ": " + e.getMessage(), e); } } } @@ -1733,27 +1900,33 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { String authorName = (String) dbObject.get(FieldNames.REGATTA_LOG_EVENT_AUTHOR_NAME.name()); Number authorPriority = (Number) dbObject.get(FieldNames.REGATTA_LOG_EVENT_AUTHOR_PRIORITY.name()); author = new LogEventAuthorImpl(authorName, authorPriority.intValue()); - //CloseOpenEnded, DeviceCompMapping, DeviceMarkMapping, RegisterComp, Revoke + // CloseOpenEnded, DeviceCompMapping, DeviceMarkMapping, RegisterComp, Revoke String eventClass = (String) dbObject.get(FieldNames.REGATTA_LOG_EVENT_CLASS.name()); if (eventClass.equals(RegattaLogDeviceCompetitorMappingEvent.class.getSimpleName())) { - return loadRegattaLogDeviceCompetitorMappingEvent(createdAt, author, logicalTimePoint, id, dbObject, regattaLogIdentifier, o); + return loadRegattaLogDeviceCompetitorMappingEvent(createdAt, author, logicalTimePoint, id, dbObject, + regattaLogIdentifier, o); } else if (eventClass.equals(RegattaLogDeviceCompetitorBravoMappingEventImpl.class.getSimpleName())) { return loadRegattaLogDeviceCompetitorBravoMappingEvent(createdAt, author, logicalTimePoint, id, dbObject, regattaLogIdentifier, o); } else if (eventClass.equals(RegattaLogDeviceMarkMappingEvent.class.getSimpleName())) { - return loadRegattaLogDeviceMarkMappingEvent(createdAt, author, logicalTimePoint, id, dbObject, regattaLogIdentifier, o); + return loadRegattaLogDeviceMarkMappingEvent(createdAt, author, logicalTimePoint, id, dbObject, + regattaLogIdentifier, o); } else if (eventClass.equals(RegattaLogCloseOpenEndedDeviceMappingEvent.class.getSimpleName())) { return loadRegattaLogCloseOpenEndedDeviceMappingEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogRegisterBoatEvent.class.getSimpleName())) { return loadRegattaLogRegisterBoatEvent(createdAt, author, logicalTimePoint, id, dbObject); + } else if (eventClass.equals(RegattaLogRegisterEntryEvent.class.getSimpleName())) { + return loadRegattaLogRegisterEntryEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogRegisterCompetitorEvent.class.getSimpleName())) { return loadRegattaLogRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogRegisterCompetitorAndBoatEvent.class.getSimpleName())) { return loadRegattaLogRegisterCompetitorAndBoatEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogSetCompetitorTimeOnTimeFactorEvent.class.getSimpleName())) { return loadRegattaLogSetCompetitorTimeOnTimeFactorEvent(createdAt, author, logicalTimePoint, id, dbObject); - } else if (eventClass.equals(RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent.class.getSimpleName())) { - return loadRegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent(createdAt, author, logicalTimePoint, id, dbObject); + } else if (eventClass + .equals(RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent.class.getSimpleName())) { + return loadRegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent(createdAt, author, + logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogDefineMarkEvent.class.getSimpleName())) { return loadRegattaLogDefineMarkEvent(createdAt, author, logicalTimePoint, id, dbObject); } else if (eventClass.equals(RegattaLogRevokeEvent.class.getSimpleName())) { @@ -1768,6 +1941,12 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return comp; } + private CompetitorWithBoat getCompetitorWithBoatByID(DBObject dbObject) { + Serializable competitorId = (Serializable) dbObject.get(FieldNames.REGATTA_LOG_COMPETITOR_ID.name()); + CompetitorWithBoat comp = baseDomainFactory.getCompetitorStore().getExistingCompetitorWithBoatById(competitorId); + return comp; + } + private Boat getBoatByID(DBObject dbObject) { Serializable boatId = (Serializable) dbObject.get(FieldNames.REGATTA_LOG_BOAT_ID.name()); Boat boat = baseDomainFactory.getCompetitorStore().getExistingBoatById(boatId); @@ -1778,139 +1957,169 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { final Competitor comp = getCompetitorByID(dbObject); final Double timeOnTimeFactor = (Double) dbObject.get(FieldNames.REGATTA_LOG_TIME_ON_TIME_FACTOR.name()); - return new RegattaLogSetCompetitorTimeOnTimeFactorEventImpl(createdAt, logicalTimePoint, author, id, comp, timeOnTimeFactor); + return new RegattaLogSetCompetitorTimeOnTimeFactorEventImpl(createdAt, logicalTimePoint, author, id, comp, + timeOnTimeFactor); } private RegattaLogEvent loadRegattaLogSetCompetitorTimeOnTimeFactorEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { final Competitor comp = getCompetitorByID(dbObject); - final Double timeOnDistanceSecondsAllowancePerNauticalMile = (Double) dbObject.get(FieldNames.REGATTA_LOG_TIME_ON_DISTANCE_SECONDS_ALLOWANCE_PER_NAUTICAL_MILE.name()); - final Duration timeOnDistanceAllowancePerNauticalMile = timeOnDistanceSecondsAllowancePerNauticalMile == null ? null : - new MillisecondsDurationImpl((long) (timeOnDistanceSecondsAllowancePerNauticalMile*1000)); - return new RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl(createdAt, logicalTimePoint, author, id, comp, timeOnDistanceAllowancePerNauticalMile); + final Double timeOnDistanceSecondsAllowancePerNauticalMile = (Double) dbObject + .get(FieldNames.REGATTA_LOG_TIME_ON_DISTANCE_SECONDS_ALLOWANCE_PER_NAUTICAL_MILE.name()); + final Duration timeOnDistanceAllowancePerNauticalMile = timeOnDistanceSecondsAllowancePerNauticalMile == null + ? null : new MillisecondsDurationImpl((long) (timeOnDistanceSecondsAllowancePerNauticalMile * 1000)); + return new RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl(createdAt, logicalTimePoint, + author, id, comp, timeOnDistanceAllowancePerNauticalMile); } private RegattaLogRevokeEvent loadRegattaLogRevokeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { - Serializable revokedEventId = Helpers.tryUuidConversion( - (Serializable) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_EVENT_ID.name())); + Serializable revokedEventId = Helpers + .tryUuidConversion((Serializable) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_EVENT_ID.name())); String revokedEventType = (String) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_EVENT_TYPE.name()); String revokedEventShortInfo = (String) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_EVENT_SHORT_INFO.name()); String reason = (String) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_REASON.name()); - return new RegattaLogRevokeEventImpl(createdAt, logicalTimePoint, author, id, - revokedEventId, revokedEventType, revokedEventShortInfo, reason); - } - - private RegattaLogEvent loadRegattaLogDefineMarkEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { - Mark mark = loadMark((DBObject) dbObject.get(FieldNames.REGATTA_LOG_MARK.name())); - return new RegattaLogDefineMarkEventImpl(createdAt, author, logicalTimePoint, id, mark); + return new RegattaLogRevokeEventImpl(createdAt, logicalTimePoint, author, id, revokedEventId, revokedEventType, + revokedEventShortInfo, reason); } - private RegattaLogRegisterCompetitorEvent loadRegattaLogRegisterCompetitorEvent(TimePoint createdAt, AbstractLogEventAuthor author, + private RegattaLogEvent loadRegattaLogDefineMarkEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { - Competitor comp = getCompetitorByID(dbObject); + Mark mark = loadMark((DBObject) dbObject.get(FieldNames.REGATTA_LOG_MARK.name())); + return new RegattaLogDefineMarkEventImpl(createdAt, author, logicalTimePoint, id, mark); + } + + private RegattaLogRegisterCompetitorEvent loadRegattaLogRegisterCompetitorEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { + CompetitorWithBoat comp = getCompetitorWithBoatByID(dbObject); final RegattaLogRegisterCompetitorEvent result; if (comp == null) { result = null; - logger.log(Level.SEVERE, "Couldn't resolve competitor with ID "+dbObject.get(FieldNames.REGATTA_LOG_COMPETITOR_ID.name())+ - " from registration event with ID "+id+". Skipping this competitor registration."); + logger.log(Level.SEVERE, + "Couldn't resolve competitor with ID " + dbObject.get(FieldNames.REGATTA_LOG_COMPETITOR_ID.name()) + + " from registration event with ID " + id + ". Skipping this competitor registration."); } else { result = new RegattaLogRegisterCompetitorEventImpl(createdAt, logicalTimePoint, author, id, comp); } return result; } - private RegattaLogRegisterBoatEvent loadRegattaLogRegisterBoatEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { + private RegattaLogRegisterBoatEvent loadRegattaLogRegisterBoatEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { Boat boat = getBoatByID(dbObject); final RegattaLogRegisterBoatEvent result; if (boat == null) { result = null; - logger.log(Level.SEVERE, "Couldn't resolve boat with ID "+dbObject.get(FieldNames.REGATTA_LOG_BOAT_ID.name())+ - " from registration event with ID "+id+". Skipping this boat registration."); + logger.log(Level.SEVERE, + "Couldn't resolve boat with ID " + dbObject.get(FieldNames.REGATTA_LOG_BOAT_ID.name()) + + " from registration event with ID " + id + ". Skipping this boat registration."); } else { result = new RegattaLogRegisterBoatEventImpl(createdAt, logicalTimePoint, author, id, boat); } return result; } - private RegattaLogRegisterCompetitorAndBoatEvent loadRegattaLogRegisterCompetitorAndBoatEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { + private RegattaLogRegisterEntryEvent loadRegattaLogRegisterEntryEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { + Competitor comp = getCompetitorByID(dbObject); + final RegattaLogRegisterEntryEvent result; + if (comp == null) { + result = null; + logger.log(Level.SEVERE, + "Couldn't resolve competitor with ID " + dbObject.get(FieldNames.REGATTA_LOG_COMPETITOR_ID.name()) + + " from registration event with ID " + id + ". Skipping this competitor registration."); + } else { + result = new RegattaLogRegisterEntryEventImpl(createdAt, logicalTimePoint, author, id, comp); + } + return result; + } + + private RegattaLogRegisterCompetitorAndBoatEvent loadRegattaLogRegisterCompetitorAndBoatEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { Competitor comp = getCompetitorByID(dbObject); Boat boat = getBoatByID(dbObject); final RegattaLogRegisterCompetitorAndBoatEvent result; if (comp == null || boat == null) { result = null; if (comp == null) { - logger.log(Level.SEVERE, "Couldn't resolve competitor with ID "+dbObject.get(FieldNames.REGATTA_LOG_COMPETITOR_ID.name())+ - " from registration event with ID "+id+". Skipping this competitor registration."); + logger.log(Level.SEVERE, "Couldn't resolve competitor with ID " + + dbObject.get(FieldNames.REGATTA_LOG_COMPETITOR_ID.name()) + + " from registration event with ID " + id + ". Skipping this competitor registration."); } if (boat == null) { - logger.log(Level.SEVERE, "Couldn't resolve boat with ID "+dbObject.get(FieldNames.REGATTA_LOG_BOAT_ID.name())+ - " from registration event with ID "+id+". Skipping this competitor registration."); + logger.log(Level.SEVERE, + "Couldn't resolve boat with ID " + dbObject.get(FieldNames.REGATTA_LOG_BOAT_ID.name()) + + " from registration event with ID " + id + + ". Skipping this competitor registration."); } } else { - result = new RegattaLogRegisterCompetitorAndBoatEventImpl(createdAt, logicalTimePoint, author, id, comp, boat); + result = new RegattaLogRegisterCompetitorAndBoatEventImpl(createdAt, logicalTimePoint, author, id, comp, + boat); } return result; } - private RegattaLogCloseOpenEndedDeviceMappingEvent loadRegattaLogCloseOpenEndedDeviceMappingEvent(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { - Serializable deviceMappingEventId = Helpers.tryUuidConversion((Serializable) dbObject.get( - FieldNames.REGATTA_LOG_DEVICE_MAPPING_EVENT_ID.name())); + private RegattaLogCloseOpenEndedDeviceMappingEvent loadRegattaLogCloseOpenEndedDeviceMappingEvent( + TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, + DBObject dbObject) { + Serializable deviceMappingEventId = Helpers + .tryUuidConversion((Serializable) dbObject.get(FieldNames.REGATTA_LOG_DEVICE_MAPPING_EVENT_ID.name())); TimePoint closingTimePointInclusive = loadTimePoint(dbObject, FieldNames.REGATTA_LOG_CLOSING_TIMEPOINT); return new RegattaLogCloseOpenEndedDeviceMappingEventImpl(createdAt, author, logicalTimePoint, id, deviceMappingEventId, closingTimePointInclusive); } - private RegattaLogDeviceMarkMappingEvent loadRegattaLogDeviceMarkMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, DBObject dbObject, RegattaLikeIdentifier regattaLogIdentifier, DBObject outerDBObject) { + private RegattaLogDeviceMarkMappingEvent loadRegattaLogDeviceMarkMappingEvent(TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject, + RegattaLikeIdentifier regattaLogIdentifier, DBObject outerDBObject) { DeviceIdentifier device = null; try { - device = loadDeviceId(deviceIdentifierServiceFinder, - (DBObject) dbObject.get(FieldNames.DEVICE_ID.name())); + 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(); } - //have to load complete mark, as no order is guaranteed for loading of racelog events + // have to load complete mark, as no order is guaranteed for loading of racelog events Mark mappedTo = loadMark((DBObject) dbObject.get(FieldNames.MARK.name())); @SuppressWarnings("deprecation") // used only for auto-migration; may be removed in future releases final FieldNames deprecatedFromFieldName = FieldNames.RACE_LOG_FROM; @SuppressWarnings("deprecation") // used only for auto-migration; may be removed in future releases final FieldNames deprecatedToFieldName = FieldNames.RACE_LOG_TO; - Triple times = loadFromToTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM, deprecatedFromFieldName, FieldNames.REGATTA_LOG_TO, deprecatedToFieldName); + Triple times = loadFromToTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM, + deprecatedFromFieldName, FieldNames.REGATTA_LOG_TO, deprecatedToFieldName); final TimePoint from = times.getA(); final TimePoint to = times.getB(); - final RegattaLogDeviceMarkMappingEventImpl result = new RegattaLogDeviceMarkMappingEventImpl(createdAt, logicalTimePoint, author, id, mappedTo, device, from, to); + final RegattaLogDeviceMarkMappingEventImpl result = new RegattaLogDeviceMarkMappingEventImpl(createdAt, + logicalTimePoint, author, id, mappedTo, device, from, to); final boolean needsMigration = times.getC(); if (needsMigration) { // remove old version of mapping event - WriteResult removeResult = database.getCollection(CollectionNames.REGATTA_LOGS.name()).remove(outerDBObject); + WriteResult removeResult = database.getCollection(CollectionNames.REGATTA_LOGS.name()) + .remove(outerDBObject); assert removeResult.getN() == 1; // and then insert using the fixed storage implementation - new MongoObjectFactoryImpl(database, serviceFinderFactory).storeRegattaLogEvent(regattaLogIdentifier, result); + new MongoObjectFactoryImpl(database, serviceFinderFactory).storeRegattaLogEvent(regattaLogIdentifier, + result); } return result; } /** * Loads a from and a to time point from fromField and toField of dbObject. - * If the fromField is not found, the fromFieldDeprecated is attempted. If found, migration - * is deemed necessary, expressed by returning true in the {@link Triple#getC()} component of the result. - * Same for the to-field. + * If the fromField is not found, the fromFieldDeprecated is attempted. If found, + * migration is deemed necessary, expressed by returning true in the {@link Triple#getC()} component of + * the result. Same for the to-field. * - * @return the from-time in {@link Triple#getA()}, the to-time in {@link Triple#getB()} and whether or not migration is - * necessary because a value was only found in a deprecated field in {@link Triple#getC()}. + * @return the from-time in {@link Triple#getA()}, the to-time in {@link Triple#getB()} and whether or not migration + * is necessary because a value was only found in a deprecated field in {@link Triple#getC()}. */ - private Triple loadFromToTimePoint(final DBObject dbObject, FieldNames fromField, FieldNames fromFieldDeprecated, - FieldNames toField, FieldNames toFieldDeprecated) { + private Triple loadFromToTimePoint(final DBObject dbObject, FieldNames fromField, + FieldNames fromFieldDeprecated, FieldNames toField, FieldNames toFieldDeprecated) { boolean needsMigration = false; TimePoint from = loadTimePoint(dbObject, fromField); if (from == null) { - // see bug 2733: erroneously, some records before the fix were written using RACE_LOG_FROM instead of REGATTA_LOG_FROM + // see bug 2733: erroneously, some records before the fix were written using RACE_LOG_FROM instead of + // REGATTA_LOG_FROM // If such a case is found here, migrate the record. from = loadTimePoint(dbObject, fromFieldDeprecated); if (from != null) { @@ -1919,7 +2128,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } TimePoint to = loadTimePoint(dbObject, toField); if (to == null) { - // see bug 2733: erroneously, some records before the fix were written using RACE_LOG_FROM instead of REGATTA_LOG_FROM + // see bug 2733: erroneously, some records before the fix were written using RACE_LOG_FROM instead of + // REGATTA_LOG_FROM // If such a case is found here, migrate the record. to = loadTimePoint(dbObject, toFieldDeprecated); if (to != null) { @@ -1928,42 +2138,44 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } return new Triple<>(from, to, needsMigration); } - + private RegattaLogDeviceCompetitorMappingEvent loadRegattaLogDeviceCompetitorMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, final DBObject dbObject, RegattaLikeIdentifier regattaLogIdentifier, DBObject outerDBObject) { DeviceIdentifier device = null; try { - device = loadDeviceId(deviceIdentifierServiceFinder, - (DBObject) dbObject.get(FieldNames.DEVICE_ID.name())); + 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(); } final Serializable competitorId = (Serializable) dbObject.get(FieldNames.COMPETITOR_ID.name()); - Competitor mappedTo = baseDomainFactory.getExistingCompetitorById( - competitorId); + Competitor mappedTo = baseDomainFactory.getExistingCompetitorById(competitorId); final RegattaLogDeviceCompetitorMappingEventImpl result; if (mappedTo == null) { - logger.severe("Found a "+RegattaLogDeviceCompetitorMappingEventImpl.class.getName()+ - " event but couldn't find competitor with ID "+competitorId); + logger.severe("Found a " + RegattaLogDeviceCompetitorMappingEventImpl.class.getName() + + " event but couldn't find competitor with ID " + competitorId); result = null; } else { @SuppressWarnings("deprecation") // used only for auto-migration; may be removed in future releases final FieldNames deprecatedFromFieldName = FieldNames.RACE_LOG_FROM; @SuppressWarnings("deprecation") // used only for auto-migration; may be removed in future releases final FieldNames deprecatedToFieldName = FieldNames.RACE_LOG_TO; - Triple times = loadFromToTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM, deprecatedFromFieldName, FieldNames.REGATTA_LOG_TO, deprecatedToFieldName); + Triple times = loadFromToTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM, + deprecatedFromFieldName, FieldNames.REGATTA_LOG_TO, deprecatedToFieldName); final TimePoint from = times.getA(); final TimePoint to = times.getB(); final boolean needsMigration = times.getC(); - result = new RegattaLogDeviceCompetitorMappingEventImpl(createdAt, logicalTimePoint, author, id, mappedTo, device, from, to); + result = new RegattaLogDeviceCompetitorMappingEventImpl(createdAt, logicalTimePoint, author, id, mappedTo, + device, from, to); if (needsMigration) { // remove old version of mapping event - WriteResult removeResult = database.getCollection(CollectionNames.REGATTA_LOGS.name()).remove(outerDBObject); + WriteResult removeResult = database.getCollection(CollectionNames.REGATTA_LOGS.name()) + .remove(outerDBObject); assert removeResult.getN() == 1; // and then insert using the fixed storage implementation - new MongoObjectFactoryImpl(database, serviceFinderFactory).storeRegattaLogEvent(regattaLogIdentifier, result); + new MongoObjectFactoryImpl(database, serviceFinderFactory).storeRegattaLogEvent(regattaLogIdentifier, + result); } } return result; @@ -1979,8 +2191,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { logger.log(Level.WARNING, "Could not load deviceId for RaceLogEvent", e); e.printStackTrace(); } - Competitor mappedTo = baseDomainFactory.getExistingCompetitorById((Serializable) dbObject - .get(FieldNames.COMPETITOR_ID.name())); + Competitor mappedTo = baseDomainFactory + .getExistingCompetitorById((Serializable) dbObject.get(FieldNames.COMPETITOR_ID.name())); @SuppressWarnings("deprecation") // used only for auto-migration; may be removed in future releases final FieldNames deprecatedFromFieldName = FieldNames.RACE_LOG_FROM; @@ -2020,15 +2232,17 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { CourseBase courseData = new CourseDataImpl(courseName); int i = 0; for (Object object : dbCourseList) { - DBObject dbObject = (DBObject) object; + DBObject dbObject = (DBObject) object; Waypoint waypoint = null; PassingInstruction passingInstructions = null; String waypointPassingInstruction = (String) dbObject.get(FieldNames.WAYPOINT_PASSINGINSTRUCTIONS.name()); if (waypointPassingInstruction == null) { waypointPassingInstruction = (String) dbObject.get(FieldNames.WAYPOINT_PASSINGSIDE.name()); - if(waypointPassingInstruction != null) { - logger.info("Migrating PassingInstruction "+waypointPassingInstruction+" to field name WAYPOINT_PASSINGINSTRUCTIONS"); - if((i==0||i==dbCourseList.size()-1)&&waypointPassingInstruction.toLowerCase().equals("gate")){ + if (waypointPassingInstruction != null) { + logger.info("Migrating PassingInstruction " + waypointPassingInstruction + + " to field name WAYPOINT_PASSINGINSTRUCTIONS"); + if ((i == 0 || i == dbCourseList.size() - 1) + && waypointPassingInstruction.toLowerCase().equals("gate")) { logger.warning("Changing PassingInstructions of first or last Waypoint from Gate to Line."); waypointPassingInstruction = "Line"; } @@ -2058,11 +2272,13 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { Mark mark = loadMark((DBObject) dbObject.get(FieldNames.CONTROLPOINT_VALUE.name())); controlPoint = mark; } else if (controlPointClass.equals("Gate")) { - ControlPointWithTwoMarks cpwtm = loadControlPointWithTwoMarks((DBObject) dbObject.get(FieldNames.CONTROLPOINT_VALUE.name())); + ControlPointWithTwoMarks cpwtm = loadControlPointWithTwoMarks( + (DBObject) dbObject.get(FieldNames.CONTROLPOINT_VALUE.name())); dbObject.put(FieldNames.CONTROLPOINT_CLASS.name(), ControlPointWithTwoMarks.class.getSimpleName()); controlPoint = cpwtm; } else if (controlPointClass.equals(ControlPointWithTwoMarks.class.getSimpleName())) { - ControlPointWithTwoMarks cpwtm = loadControlPointWithTwoMarks((DBObject) dbObject.get(FieldNames.CONTROLPOINT_VALUE.name())); + ControlPointWithTwoMarks cpwtm = loadControlPointWithTwoMarks( + (DBObject) dbObject.get(FieldNames.CONTROLPOINT_VALUE.name())); controlPoint = cpwtm; } } @@ -2093,7 +2309,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { DBObject dbLeft = (DBObject) dbObject.get(FieldNames.CONTROLPOINTWITHTWOMARKS_LEFT.name()); if (dbLeft == null) { dbLeft = (DBObject) dbObject.get(FieldNames.GATE_LEFT.name()); - logger.info("Migrating left Mark of ControlPointWithTwoMarks " + controlPointName + " from old field GATE_LEFT to CONTROLPOINTWITHTWOMARKS_LEFT"); + logger.info("Migrating left Mark of ControlPointWithTwoMarks " + controlPointName + + " from old field GATE_LEFT to CONTROLPOINTWITHTWOMARKS_LEFT"); dbObject.put(FieldNames.CONTROLPOINTWITHTWOMARKS_LEFT.name(), dbLeft); dbObject.removeField(FieldNames.GATE_LEFT.name()); } @@ -2101,12 +2318,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { DBObject dbRight = (DBObject) dbObject.get(FieldNames.CONTROLPOINTWITHTWOMARKS_RIGHT.name()); if (dbRight == null) { dbRight = (DBObject) dbObject.get(FieldNames.GATE_RIGHT.name()); - logger.info("Migrating right Mark of ControlPointWithTwoMarks " + controlPointName + " from old field GATE_RIGHT to CONTROLPOINTWITHTWOMARKS_RIGHT"); + logger.info("Migrating right Mark of ControlPointWithTwoMarks " + controlPointName + + " from old field GATE_RIGHT to CONTROLPOINTWITHTWOMARKS_RIGHT"); dbObject.put(FieldNames.CONTROLPOINTWITHTWOMARKS_RIGHT.name(), dbRight); dbObject.removeField(FieldNames.GATE_RIGHT.name()); } Mark rightMark = loadMark(dbRight); - ControlPointWithTwoMarks gate = baseDomainFactory.createControlPointWithTwoMarks(controlPointId, leftMark, rightMark, controlPointName); + ControlPointWithTwoMarks gate = baseDomainFactory.createControlPointWithTwoMarks(controlPointId, leftMark, + rightMark, controlPointName); return gate; } @@ -2119,13 +2338,30 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { String markShape = (String) dbObject.get(FieldNames.MARK_SHAPE.name()); Object markTypeRaw = dbObject.get(FieldNames.MARK_TYPE.name()); MarkType markType = markTypeRaw == null ? null : MarkType.valueOf((String) markTypeRaw); - + Mark mark = baseDomainFactory.getOrCreateMark(markId, markName, markType, markColor, markShape, markPattern); return mark; } @Override - public Collection loadAllCompetitors() { + public Collection loadAllCompetitors() { + ArrayList result = new ArrayList<>(); + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITHOUT_BOAT.name()); + try { + for (DBObject o : collection.find()) { + JSONObject json = Helpers.toJSONObjectSafe(new JSONParser().parse(JSON.serialize(o))); + Competitor c = competitorDeserializer.deserialize(json); + result.add(c); + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load competitors."); + logger.log(Level.SEVERE, "loadCompetitors", e); + } + return result; + } + + @Override + public Collection loadAllCompetitorsWithBoat() { ArrayList result = new ArrayList<>(); DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); try { @@ -2162,7 +2398,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { public Iterable> loadAllDeviceConfigurations() { Map result = new HashMap<>(); DBCollection configurationCollection = database.getCollection(CollectionNames.CONFIGURATIONS.name()); - + try { for (DBObject dbObject : configurationCollection.find()) { Util.Pair entry = loadConfigurationEntry(dbObject); @@ -2172,20 +2408,21 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load configurations."); logger.log(Level.SEVERE, "loadAllDeviceConfigurations", e); } - + return result.entrySet(); } private Util.Pair loadConfigurationEntry(DBObject dbObject) { DBObject matcherObject = (DBObject) dbObject.get(FieldNames.CONFIGURATION_MATCHER.name()); DBObject configObject = (DBObject) dbObject.get(FieldNames.CONFIGURATION_CONFIG.name()); - return new Util.Pair(loadConfigurationMatcher(matcherObject), + return new Util.Pair(loadConfigurationMatcher(matcherObject), loadConfiguration(configObject)); } private DeviceConfigurationMatcher loadConfigurationMatcher(DBObject matcherObject) { List clientIdentifiers = new ArrayList(); - BasicDBList clientIdentifiersObject = (BasicDBList) matcherObject.get(FieldNames.CONFIGURATION_MATCHER_CLIENTS.name()); + BasicDBList clientIdentifiersObject = (BasicDBList) matcherObject + .get(FieldNames.CONFIGURATION_MATCHER_CLIENTS.name()); if (clientIdentifiersObject != null) { for (Object clientIdentifier : clientIdentifiersObject) { clientIdentifiers.add(clientIdentifier.toString()); @@ -2201,25 +2438,27 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { JSONObject json = Helpers.toJSONObjectSafe(new JSONParser().parse(JSON.serialize(configObject))); configuration = deserializer.deserialize(json); } catch (JsonDeserializationException | ParseException e) { - logger.log(Level.SEVERE, "Error parsing configuration object from MongoDB, falling back to empty configuration."); + logger.log(Level.SEVERE, + "Error parsing configuration object from MongoDB, falling back to empty configuration."); logger.log(Level.SEVERE, "loadConfiguration", e); configuration = new DeviceConfigurationImpl(new RegattaConfigurationImpl()); } return configuration; } - + private DeviceIdentifier loadDeviceId( TypeBasedServiceFinder deviceIdentifierServiceFinder, DBObject deviceId) - throws TransformationException, NoCorrespondingServiceRegisteredException { + 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); + return deviceIdentifierServiceFinder.findService(deviceType).deserialize(deviceTypeId, deviceType, + stringRepresentation); } catch (TransformationException e) { - return new PlaceHolderDeviceIdentifierSerializationHandler().deserialize( - stringRepresentation, deviceType, stringRepresentation); + return new PlaceHolderDeviceIdentifierSerializationHandler().deserialize(stringRepresentation, deviceType, + stringRepresentation); } } @@ -2245,7 +2484,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } return resultUrls; } - + private ImageDescriptor loadImage(DBObject dbObject) { ImageDescriptor image = null; URL imageURL = loadURL(dbObject, FieldNames.IMAGE_URL); @@ -2253,8 +2492,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { String title = (String) dbObject.get(FieldNames.IMAGE_TITLE.name()); String subtitle = (String) dbObject.get(FieldNames.IMAGE_SUBTITLE.name()); String copyright = (String) dbObject.get(FieldNames.IMAGE_COPYRIGHT.name()); - String localeRaw = (String) dbObject.get(FieldNames.IMAGE_LOCALE.name()); - Locale locale = localeRaw != null ? Locale.forLanguageTag(localeRaw) : null; + String localeRaw = (String) dbObject.get(FieldNames.IMAGE_LOCALE.name()); + Locale locale = localeRaw != null ? Locale.forLanguageTag(localeRaw) : null; Number imageWidth = (Number) dbObject.get(FieldNames.IMAGE_WIDTH_IN_PX.name()); Number imageHeight = (Number) dbObject.get(FieldNames.IMAGE_HEIGHT_IN_PX.name()); TimePoint createdAtDate = loadTimePoint(dbObject, FieldNames.IMAGE_CREATEDATDATE); @@ -2277,18 +2516,18 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } return image; } - + private VideoDescriptor loadVideo(DBObject dbObject) { VideoDescriptor video = null; URL videoURL = loadURL(dbObject, FieldNames.VIDEO_URL); - if(videoURL != null) { + if (videoURL != null) { String title = (String) dbObject.get(FieldNames.VIDEO_TITLE.name()); String subtitle = (String) dbObject.get(FieldNames.VIDEO_SUBTITLE.name()); String copyright = (String) dbObject.get(FieldNames.VIDEO_COPYRIGHT.name()); Object mimeTypeRaw = dbObject.get(FieldNames.VIDEO_MIMETYPE.name()); MimeType mimeType = mimeTypeRaw == null ? null : MimeType.valueOf((String) mimeTypeRaw); - String localeRaw = (String) dbObject.get(FieldNames.VIDEO_LOCALE.name()); - Locale locale = localeRaw != null ? Locale.forLanguageTag(localeRaw) : null; + String localeRaw = (String) dbObject.get(FieldNames.VIDEO_LOCALE.name()); + Locale locale = localeRaw != null ? Locale.forLanguageTag(localeRaw) : null; TimePoint createdAtDate = loadTimePoint(dbObject, FieldNames.VIDEO_CREATEDATDATE); BasicDBList tags = (BasicDBList) dbObject.get(FieldNames.VIDEO_TAGS.name()); Number lengthInSeconds = (Number) dbObject.get(FieldNames.VIDEO_LENGTH_IN_SECONDS.name()); @@ -2314,18 +2553,19 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { private URL loadURL(DBObject dbObject, FieldNames field) { URL result = null; String urlAsString = (String) dbObject.get(field.name()); - if(urlAsString != null) { + if (urlAsString != null) { try { result = new URL(urlAsString); } catch (MalformedURLException e) { - logger.severe("Error parsing URL '"+urlAsString+"' in field "+field.name()+"."); + logger.severe("Error parsing URL '" + urlAsString + "' in field " + field.name() + "."); } } - return result; + return result; } - + /** - * Legacy code to support conversion of old image and video URLs + * Legacy code to support conversion of old image and video URLs + * * @param event * @param eventDBObject */ @@ -2334,22 +2574,24 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { List imageURLs = new ArrayList(); List sponsorImageURLs = new ArrayList(); List videoURLs = new ArrayList(); - + String logoImageURLAsString = (String) eventDBObject.get(FieldNames.EVENT_LOGO_IMAGE_URL.name()); if (logoImageURLAsString != null) { try { logoImageURL = new URL(logoImageURLAsString); } catch (MalformedURLException e) { - logger.severe("Error parsing logo image URL "+logoImageURLAsString+" for event "+event.getName()+". Ignoring this URL."); + logger.severe("Error parsing logo image URL " + logoImageURLAsString + " for event " + event.getName() + + ". Ignoring this URL."); } } BasicDBList imageURLsJson = (BasicDBList) eventDBObject.get(FieldNames.EVENT_IMAGE_URLS.name()); if (imageURLsJson != null) { for (Object imageURL : imageURLsJson) { try { - imageURLs.add(new URL((String) imageURL)); + imageURLs.add(new URL((String) imageURL)); } catch (MalformedURLException e) { - logger.severe("Error parsing image URL "+imageURL+" for event "+event.getName()+". Ignoring this image URL."); + logger.severe("Error parsing image URL " + imageURL + " for event " + event.getName() + + ". Ignoring this image URL."); } } } @@ -2359,7 +2601,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { try { videoURLs.add(new URL((String) videoURL)); } catch (MalformedURLException e) { - logger.severe("Error parsing video URL "+videoURL+" for event "+event.getName()+". Ignoring this video URL."); + logger.severe("Error parsing video URL " + videoURL + " for event " + event.getName() + + ". Ignoring this video URL."); } } } @@ -2369,7 +2612,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { try { sponsorImageURLs.add(new URL((String) sponsorImageURL)); } catch (MalformedURLException e) { - logger.severe("Error parsing sponsor image URL "+sponsorImageURL+" for event "+event.getName()+". Ignoring this sponsor image URL."); + logger.severe("Error parsing sponsor image URL " + sponsorImageURL + " for event " + event.getName() + + ". Ignoring this sponsor image URL."); } } } @@ -2378,21 +2622,26 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { private boolean loadLegacySailorsInfoWebsiteURL(Event event, DBObject eventDBObject) { final boolean modified; - final String sailorsInfoWebSiteURLAsString = (String) eventDBObject.get(FieldNames.EVENT_SAILORS_INFO_WEBSITE_URL.name()); + final String sailorsInfoWebSiteURLAsString = (String) eventDBObject + .get(FieldNames.EVENT_SAILORS_INFO_WEBSITE_URL.name()); if (sailorsInfoWebSiteURLAsString != null) { try { - // The legacy sailors info URL (only used at Kieler/Travemuender Woche events) used to have 2 localized versions: + // The legacy sailors info URL (only used at Kieler/Travemuender Woche events) used to have 2 localized + // versions: // The German version with no suffix (e.g. http://sailorsinfo.travemuender-woche.com) - // The English/international version with "/en" suffix (e.g. http://sailorsinfo.travemuender-woche.com/en) + // The English/international version with "/en" suffix (e.g. + // http://sailorsinfo.travemuender-woche.com/en) if (!event.hasSailorsInfoWebsiteURL(null)) { - final String englishURL = sailorsInfoWebSiteURLAsString + (sailorsInfoWebSiteURLAsString.endsWith("/") ? "" : "/") + "en"; + final String englishURL = sailorsInfoWebSiteURLAsString + + (sailorsInfoWebSiteURLAsString.endsWith("/") ? "" : "/") + "en"; event.setSailorsInfoWebsiteURL(null, new URL(englishURL)); } if (!event.hasSailorsInfoWebsiteURL(Locale.GERMAN)) { event.setSailorsInfoWebsiteURL(Locale.GERMAN, new URL(sailorsInfoWebSiteURLAsString)); } } catch (MalformedURLException e) { - logger.severe("Error parsing sailors info website URL "+sailorsInfoWebSiteURLAsString+" for event "+event.getName()+". Ignoring this URL."); + logger.severe("Error parsing sailors info website URL " + sailorsInfoWebSiteURLAsString + " for event " + + event.getName() + ". Ignoring this URL."); } modified = true; } else { @@ -2402,18 +2651,21 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } @Override - public ConnectivityParametersLoadingResult loadConnectivityParametersForRacesToRestore(Consumer callback) { - final DBCollection collection = database.getCollection(CollectionNames.CONNECTIVITY_PARAMS_FOR_RACES_TO_BE_RESTORED.name()); + public ConnectivityParametersLoadingResult loadConnectivityParametersForRacesToRestore( + Consumer callback) { + final DBCollection collection = database + .getCollection(CollectionNames.CONNECTIVITY_PARAMS_FOR_RACES_TO_BE_RESTORED.name()); final DBCursor cursor = collection.find(); final int count = cursor.count(); - logger.info("Restoring "+count+" races"); + logger.info("Restoring " + count + " races"); final List restoreParameters = new ArrayList<>(); // consume all elements quickly to avoid cursor/DB timeouts while restoring many races; // MongoDB cursors by default time out after ten minutes if no more batch (of by default 100 elements) // has been requested during this time. Util.addAll(cursor, restoreParameters); - logger.info("Obtained "+restoreParameters.size()+" race parameters to restore"); - final ScheduledExecutorService backgroundExecutor = ThreadPoolUtil.INSTANCE.getDefaultBackgroundTaskThreadPoolExecutor(); + logger.info("Obtained " + restoreParameters.size() + " race parameters to restore"); + final ScheduledExecutorService backgroundExecutor = ThreadPoolUtil.INSTANCE + .getDefaultBackgroundTaskThreadPoolExecutor(); final Set> waiters = new HashSet<>(); logger.info("Starting to restore races"); final AtomicInteger i = new AtomicInteger(); @@ -2421,35 +2673,39 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { final FutureTask waiter = new FutureTask<>(() -> { final String type = (String) o.get(TypeBasedServiceFinder.TYPE); final int finalI = i.incrementAndGet(); - logger.info("Applying to restore race #"+ finalI +"/"+count+" of type "+type); - raceTrackingConnectivityParamsServiceFinder.applyServiceWhenAvailable(type, connectivityParamsPersistenceService -> { - logger.info("Restoring race #"+ finalI +"/"+count+" of type "+type); - final Map map = new HashMap<>(); - for (final String key : o.keySet()) { - if (!key.equals(TypeBasedServiceFinder.TYPE)) { - map.put(key, o.get(key)); - } - } - try { - final RaceTrackingConnectivityParameters params = connectivityParamsPersistenceService.mapTo(map); - if (params != null) { - callback.accept(params); - logger.info("Done restoring race #"+ finalI +"/"+count+" of type "+type); - } else { - logger.warning("Couldn't restore race #"+ finalI +"/"+count+" of type "+type+ - " because the parameters loaded from the DB couldn't be mapped. Maybe the owning leaderboard was removed?"); - } - } catch (Exception e) { - logger.log(Level.SEVERE, "Exception trying to load race #"+ finalI +"/"+count+" of type "+type+ - " from restore connectivity parameters " - + o + " with handler " + connectivityParamsPersistenceService, e); - } - }); + logger.info("Applying to restore race #" + finalI + "/" + count + " of type " + type); + raceTrackingConnectivityParamsServiceFinder.applyServiceWhenAvailable(type, + connectivityParamsPersistenceService -> { + logger.info("Restoring race #" + finalI + "/" + count + " of type " + type); + final Map map = new HashMap<>(); + for (final String key : o.keySet()) { + if (!key.equals(TypeBasedServiceFinder.TYPE)) { + map.put(key, o.get(key)); + } + } + try { + final RaceTrackingConnectivityParameters params = connectivityParamsPersistenceService + .mapTo(map); + if (params != null) { + callback.accept(params); + logger.info("Done restoring race #" + finalI + "/" + count + " of type " + type); + } else { + logger.warning("Couldn't restore race #" + finalI + "/" + count + " of type " + type + + " because the parameters loaded from the DB couldn't be mapped. Maybe the owning leaderboard was removed?"); + } + } catch (Exception e) { + logger.log(Level.SEVERE, + "Exception trying to load race #" + finalI + "/" + count + " of type " + type + + " from restore connectivity parameters " + o + " with handler " + + connectivityParamsPersistenceService, + e); + } + }); }, /* void result */ null); waiters.add(waiter); backgroundExecutor.execute(waiter); } - logger.info("Done restoring races; restored "+i+" of "+count+" races"); + logger.info("Done restoring races; restored " + i + " of " + count + " races"); return new ConnectivityParametersLoadingResult() { @Override public int getNumberOfParametersToLoad() { 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 10ef00bba75..9300d8497a4 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 @@ -63,12 +63,14 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorBravoMappingEventImpl; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.ControlPointWithTwoMarks; import com.sap.sailing.domain.base.CourseArea; @@ -121,6 +123,7 @@ import com.sap.sailing.domain.tracking.WindTrack; import com.sap.sailing.server.gateway.serialization.JsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.BoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorWithBoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.DeviceConfigurationJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.RegattaConfigurationJsonSerializer; import com.sap.sse.common.Duration; @@ -138,6 +141,7 @@ import com.sap.sse.shared.media.VideoDescriptor; public class MongoObjectFactoryImpl implements MongoObjectFactory { private static Logger logger = Logger.getLogger(MongoObjectFactoryImpl.class.getName()); private final DB database; + private final CompetitorWithBoatJsonSerializer competitorWithBoatSerializer = CompetitorWithBoatJsonSerializer.create(); private final CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create(); private final BoatJsonSerializer boatSerializer = BoatJsonSerializer.create(); private final TypeBasedServiceFinder deviceIdentifierServiceFinder; @@ -1146,7 +1150,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { storeTimePoint(event.getCreatedAt(), result, FieldNames.RACE_LOG_EVENT_CREATED_AT); result.put(FieldNames.RACE_LOG_EVENT_ID.name(), event.getId()); result.put(FieldNames.RACE_LOG_EVENT_PASS_ID.name(), event.getPassId()); - result.put(FieldNames.RACE_LOG_EVENT_INVOLVED_BOATS.name(), storeInvolvedBoatsForRaceLogEvent(event.getInvolvedBoats())); + result.put(FieldNames.RACE_LOG_EVENT_INVOLVED_BOATS.name(), storeInvolvedBoatsForRaceLogEvent(event.getInvolvedCompetitors())); storeRaceLogEventAuthor(result, event.getAuthor()); } @@ -1317,10 +1321,33 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { } return passing; } - + + @Override + public void storeCompetitorWithBoat(CompetitorWithBoat competitor) { + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); + JSONObject json = competitorWithBoatSerializer.serialize(competitor); + DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString()); + DBObject entry = (DBObject) JSON.parse(json.toString()); + collection.update(query, entry, /* upsrt */true, /* multi */false, WriteConcern.SAFE); + } + + @Override + public void storeCompetitorsWithBoat(Iterable competitors) { + if (competitors != null && !Util.isEmpty(competitors)) { + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); + List competitorsDB = new ArrayList<>(); + for (CompetitorWithBoat competitor : competitors) { + JSONObject json = competitorWithBoatSerializer.serialize(competitor); + DBObject entry = (DBObject) JSON.parse(json.toString()); + competitorsDB.add(entry); + } + collection.insert(competitorsDB); + } + } + @Override public void storeCompetitor(Competitor competitor) { - DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITHOUT_BOAT.name()); JSONObject json = competitorSerializer.serialize(competitor); DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString()); DBObject entry = (DBObject) JSON.parse(json.toString()); @@ -1330,7 +1357,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { @Override public void storeCompetitors(Iterable competitors) { if (competitors != null && !Util.isEmpty(competitors)) { - DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITHOUT_BOAT.name()); List competitorsDB = new ArrayList<>(); for (Competitor competitor : competitors) { JSONObject json = competitorSerializer.serialize(competitor); @@ -1343,6 +1370,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { @Override public void removeAllCompetitors() { + logger.info("Removing all persistent competitors"); + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS_WITHOUT_BOAT.name()); + collection.drop(); + } + + @Override + public void removeAllCompetitorsWithBoat() { logger.info("Removing all persistent competitors"); DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); collection.drop(); @@ -1350,6 +1384,14 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { @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_WITHOUT_BOAT.name()); + DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString()); + collection.remove(query, WriteConcern.SAFE); + } + + @Override + public void removeCompetitorWithBoat(CompetitorWithBoat competitor) { logger.info("Removing persistent competitor info for competitor "+competitor.getName()+" with ID "+competitor.getId()); DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString()); @@ -1564,6 +1606,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { storeRegattaLogEvent(regattaLikeId, result); } + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogRegisterEntryEvent event) { + DBObject result = createBasicRegattaLogEventDBObject(event); + result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogRegisterEntryEvent.class.getSimpleName()); + result.put(FieldNames.REGATTA_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); + storeRegattaLogEvent(regattaLikeId, result); + } + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogRegisterCompetitorEvent event) { DBObject result = createBasicRegattaLogEventDBObject(event); result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogRegisterCompetitorEvent.class.getSimpleName()); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java index 2a3d97d0671..3de5346128d 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoRegattaLogStoreVisitor.java @@ -11,6 +11,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -59,6 +60,11 @@ public class MongoRegattaLogStoreVisitor implements RegattaLogEventVisitor { mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event); } + @Override + public void visit(RegattaLogRegisterEntryEvent event) { + mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event); + } + @Override public void visit(RegattaLogRegisterCompetitorEvent event) { mongoObjectFactory.storeRegattaLogEvent(regattaLikeIdentifier, event); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java index 598a3f69546..6d79312f710 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java @@ -22,17 +22,21 @@ import org.junit.rules.Timeout; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorAndBoatEventImpl; +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.DomainFactory; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Series; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; import com.sap.sailing.domain.base.impl.FleetImpl; import com.sap.sailing.domain.base.impl.RegattaImpl; import com.sap.sailing.domain.base.impl.SeriesImpl; @@ -64,7 +68,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class CreateAndTrackWithRaceLogTest extends RaceLogTrackingTestHelper { private RacingEventService service; - + private final static BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); private final Fleet fleet = new FleetImpl("fleet"); private final String columnName = "column"; private RegattaLeaderboard leaderboard; @@ -182,13 +186,14 @@ public class CreateAndTrackWithRaceLogTest extends RaceLogTrackingTestHelper { assertFalse(raceLog.isEmpty()); // add a mapping and one fix in, one out of mapping + Boat boat1 = new BoatImpl("id12345", "boat1", boatClass, /* sailID */ null); Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", "c", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); DeviceIdentifier dev1 = new SmartphoneImeiIdentifier("dev1"); regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, 0, comp1, dev1, t(0), t(10))); addFixes0(dev1); - raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(t(), author, t(), UUID.randomUUID(), 0)); - raceLog.add(new RaceLogRegisterCompetitorEventImpl(t(), author, 0, comp1)); + raceLog.add(new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(t(), author, t(), UUID.randomUUID(), 0)); + raceLog.add(new RaceLogRegisterCompetitorAndBoatEventImpl(t(), author, 0, comp1, boat1)); raceLog.add(new RaceLogStartOfTrackingEventImpl(t(0), author, /* passId */ 0)); // start tracking adapter.startTracking(service, leaderboard, column, fleet, /* trackWind */ false, /* correctWindDirectionByMagneticDeclination */ false); @@ -261,13 +266,14 @@ public class CreateAndTrackWithRaceLogTest extends RaceLogTrackingTestHelper { adapter.denoteRaceForRaceLogTracking(service, leaderboard, column, fleet, "race"); // add a mapping and one fix in, one out of mapping + Boat boat1 = new BoatImpl("id12345", "boat1", boatClass, /* sailID */ null); Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", "c1", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); DeviceIdentifier dev1 = new SmartphoneImeiIdentifier("dev1"); regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, UUID.randomUUID(), comp1, dev1, t(0), t(10))); addFixes0(dev1); - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(t(), t(), author, UUID.randomUUID(), comp1)); + regattaLog.add(new RegattaLogRegisterCompetitorAndBoatEventImpl(t(), t(), author, UUID.randomUUID(), comp1, boat1)); raceLog.add(new RaceLogStartOfTrackingEventImpl(t(0), author, /* passId */ 0)); // start tracking diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java index 00c3b5163bd..b52b445fbb2 100755 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.logging.Level; @@ -43,7 +44,7 @@ import com.sap.sailing.domain.base.impl.CourseDataImpl; import com.sap.sailing.domain.common.CourseDesignerMode; import com.sap.sailing.domain.common.RegattaIdentifier; import com.sap.sailing.domain.common.abstractlog.NotRevokableException; -import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException; +import com.sap.sailing.domain.common.racelog.tracking.CompetitorAndBoatRegistrationOnRaceLogDisabledException; import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; import com.sap.sailing.domain.common.racelog.tracking.NotDenotableForRaceLogTrackingException; import com.sap.sailing.domain.common.racelog.tracking.NotDenotedForRaceLogTrackingException; @@ -139,9 +140,9 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { RegattaLeaderboard rLeaderboard = (RegattaLeaderboard) leaderboard; boatClass = rLeaderboard.getRegatta().getBoatClass(); } else { - if (!Util.isEmpty(raceColumn.getAllCompetitors(fleet))) { + if (!Util.isEmpty(raceColumn.getAllCompetitorsAndTheirBoats(fleet).values())) { boatClass = findDominatingBoatClass(raceColumn.getAllCompetitorsAndTheirBoats(fleet).values()); - } else if (!Util.isEmpty(raceColumn.getAllCompetitors())) { + } else if (!Util.isEmpty(raceColumn.getAllCompetitorsAndTheirBoats().values())) { boatClass = findDominatingBoatClass(raceColumn.getAllCompetitorsAndTheirBoats().values()); } else if (!Util.isEmpty(leaderboard.getAllCompetitors())) { boatClass = leaderboard.getBoatClass(); @@ -223,18 +224,18 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { @Override public void copyCompetitors(final RaceColumn fromRaceColumn, final Fleet fromFleet, final Iterable> toRaces) { - Iterable competitorsToCopy = fromRaceColumn.getAllCompetitors(fromFleet); + Map competitorsAndBoatsToCopy = fromRaceColumn.getAllCompetitorsAndTheirBoats(fromFleet); for (Pair toRace : toRaces) { final RaceColumn toRaceColumn = toRace.getA(); final Fleet toFleet = toRace.getB(); try { - if (toRaceColumn.isCompetitorRegistrationInRacelogEnabled(toFleet)) { - toRaceColumn.registerCompetitors(competitorsToCopy, toFleet); + if (toRaceColumn.isCompetitorAndBoatRegistrationInRacelogEnabled(toFleet)) { + toRaceColumn.registerCompetitorsAndBoats(competitorsAndBoatsToCopy, toFleet); } else { - toRaceColumn.enableCompetitorRegistrationOnRaceLog(toFleet); - toRaceColumn.registerCompetitors(competitorsToCopy, toFleet); + toRaceColumn.enableCompetitorAndBoatRegistrationOnRaceLog(toFleet); + toRaceColumn.registerCompetitorsAndBoats(competitorsAndBoatsToCopy, toFleet); } - } catch (CompetitorRegistrationOnRaceLogDisabledException e1) { + } catch (CompetitorAndBoatRegistrationOnRaceLogDisabledException e1) { // cannot happen as we explicitly checked successfully before, or enabled it when the check failed; still produce a log documenting this strangeness: logger.log(Level.WARNING, "Internal error: race column "+toRaceColumn.getName()+" does not accept competitor registration although it should", e1); } diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java index 3693a5abd42..9a24f11dee9 100755 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/regattalog/tracking/analyzing/test/CompetitorDeregistrationTest.java @@ -14,13 +14,20 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorDeregistrator; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sse.common.impl.MillisecondsTimePoint; public class CompetitorDeregistrationTest extends AbstractRegattaLogTrackingTest { - private final Competitor competitor = new CompetitorImpl("comp", "Comp", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - private final Competitor competitor2 = new CompetitorImpl("comp2", "Comp2", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + private final static BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); + private final static DynamicBoat boat1 = new BoatImpl("id12345", "boat1", boatClass, /* sailID */ null); + private final static DynamicBoat boat2 = new BoatImpl("id12345", "boat1", boatClass, /* sailID */ null); + private final CompetitorWithBoat competitor = new CompetitorWithBoatImpl("comp", "Comp", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null, boat1); + private final CompetitorWithBoat competitor2 = new CompetitorWithBoatImpl("comp2", "Comp2", "KYC", null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null, boat2); @Test public void testCompetitorDeregistration() { @@ -30,7 +37,7 @@ public class CompetitorDeregistrationTest extends AbstractRegattaLogTrackingTest Collections.singleton(competitor2), author); final Set events = deregistrator.analyze(); deregistrator.deregister(events); - final Set competitors = new CompetitorsInLogAnalyzer<>(log).analyze(); + final Set competitors = new CompetitorsInLogAnalyzer<>(log).analyze(); assertEquals(1, competitors.size()); assertSame(competitor, competitors.iterator().next()); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventData.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventData.java index c715c3351d9..5b7ab1c3611 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventData.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventData.java @@ -23,5 +23,5 @@ public interface RaceLogEventData extends Serializable { * A {@link RaceLogEventData} might be associated with a list of competitors, which are somehow relevant for this * kind of event. An example is a list of competitors who are marked for an individual recall. */ - List getInvolvedBoats(); + List getInvolvedCompetitors(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/MarkPassingDataFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/MarkPassingDataFinder.java index e5ead97f468..247811d4b65 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/MarkPassingDataFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/MarkPassingDataFinder.java @@ -23,11 +23,11 @@ public class MarkPassingDataFinder extends RaceLogAnalyzer(castedEvent.getInvolvedBoats().get(0), castedEvent + result.add(new Triple(castedEvent.getInvolvedCompetitors().get(0), castedEvent .getZeroBasedIndexOfPassedWaypoint(), castedEvent.getTimePointOfFixedPassing())); } else if (event instanceof RaceLogSuppressedMarkPassingsEvent){ RaceLogSuppressedMarkPassingsEvent castedEvent = (RaceLogSuppressedMarkPassingsEvent) event; - result.add(new Triple(castedEvent.getInvolvedBoats().get(0), castedEvent.getZeroBasedIndexOfFirstSuppressedWaypoint(), null)); + result.add(new Triple(castedEvent.getInvolvedCompetitors().get(0), castedEvent.getZeroBasedIndexOfFirstSuppressedWaypoint(), null)); } } return result; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/RaceLogRegisteredCompetitorsAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/RaceLogRegisteredCompetitorsAnalyzer.java index d7f8737854d..00a84487785 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/RaceLogRegisteredCompetitorsAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/RaceLogRegisteredCompetitorsAnalyzer.java @@ -6,17 +6,17 @@ import java.util.Set; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogUsesOwnCompetitorsAnalyzer; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; -public class RaceLogRegisteredCompetitorsAnalyzer extends RaceLogAnalyzer> { +public class RaceLogRegisteredCompetitorsAnalyzer extends RaceLogAnalyzer> { public RaceLogRegisteredCompetitorsAnalyzer(RaceLog raceLog) { super(raceLog); } @Override - protected Set performAnalysis() { - final Set result; + protected Set performAnalysis() { + final Set result; if (new RaceLogUsesOwnCompetitorsAnalyzer(getLog()).analyze()){ // get Events from RaceLog result = new CompetitorsInLogAnalyzer<>(getLog()).analyze(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/RaceLogRegisteredCompetitorsAndBoatsAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/RaceLogRegisteredCompetitorsAndBoatsAnalyzer.java new file mode 100644 index 00000000000..3199b98c703 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/RaceLogRegisteredCompetitorsAndBoatsAnalyzer.java @@ -0,0 +1,31 @@ +package com.sap.sailing.domain.abstractlog.race.analyzing.impl; + +import java.util.Collections; +import java.util.Map; + +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogUsesOwnCompetitorsAndBoatsAnalyzer; +import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsAndBoatsInLogAnalyzer; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; + +public class RaceLogRegisteredCompetitorsAndBoatsAnalyzer extends RaceLogAnalyzer> { + + public RaceLogRegisteredCompetitorsAndBoatsAnalyzer(RaceLog raceLog) { + super(raceLog); + } + + @Override + protected Map performAnalysis() { + final Map result; + if (new RaceLogUsesOwnCompetitorsAndBoatsAnalyzer(getLog()).analyze()){ + // get Events from RaceLog + result = new CompetitorsAndBoatsInLogAnalyzer<>(getLog()).analyze(); + } else { + // as we're explicitly only trying to find those registrations in the RaceLog, we won't + // return anything from the regatta log. + result = Collections.emptyMap(); + } + return result; + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventDataImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventDataImpl.java index 68f1f88def4..45933ee3450 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventDataImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventDataImpl.java @@ -21,7 +21,7 @@ public class RaceLogEventDataImpl implements RaceLogEventData { } @Override - public List getInvolvedBoats() { + public List getInvolvedCompetitors() { return involvedBoats; } @@ -32,6 +32,6 @@ public class RaceLogEventDataImpl implements RaceLogEventData { @Override public String toString() { - return super.toString() + ", involvedBoats: " + getInvolvedBoats() + ", passId: " + getPassId(); + return super.toString() + ", involvedBoats: " + getInvolvedCompetitors() + ", passId: " + getPassId(); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventImpl.java index 2c4092a3130..ffd67eda973 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventImpl.java @@ -36,8 +36,8 @@ public abstract class RaceLogEventImpl extends AbstractLogEventImpl getInvolvedBoats() { - return raceLogEventData.getInvolvedBoats(); + public List getInvolvedCompetitors() { + return raceLogEventData.getInvolvedCompetitors(); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFixedMarkPassingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFixedMarkPassingEventImpl.java index ebd95a0a6fe..c3ef632647b 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFixedMarkPassingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFixedMarkPassingEventImpl.java @@ -49,8 +49,8 @@ public class RaceLogFixedMarkPassingEventImpl extends RaceLogEventImpl implement @Override public String getShortInfo() { - return (getInvolvedBoats() == null || getInvolvedBoats().get(0) == null ? "Unknown" : - getInvolvedBoats().get(0).getName()) + " at mark " + getZeroBasedIndexOfPassedWaypoint() + " at " + return (getInvolvedCompetitors() == null || getInvolvedCompetitors().get(0) == null ? "Unknown" : + getInvolvedCompetitors().get(0).getName()) + " at mark " + getZeroBasedIndexOfPassedWaypoint() + " at " + getTimePointOfFixedPassing(); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRevokeEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRevokeEventImpl.java index 8f5d7560275..ab7dd407aef 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRevokeEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRevokeEventImpl.java @@ -35,8 +35,8 @@ public class RaceLogRevokeEventImpl extends RevokeEventImpl } @Override - public List getInvolvedBoats() { - return raceLogEventData.getInvolvedBoats(); + public List getInvolvedCompetitors() { + return raceLogEventData.getInvolvedCompetitors(); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogSuppressedMarkPassingsEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogSuppressedMarkPassingsEventImpl.java index f3eb85c285a..941515811f9 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogSuppressedMarkPassingsEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogSuppressedMarkPassingsEventImpl.java @@ -42,6 +42,6 @@ public class RaceLogSuppressedMarkPassingsEventImpl extends RaceLogEventImpl imp @Override public String getShortInfo() { - return getInvolvedBoats().get(0).getName() + " at mark " + getZeroBasedIndexOfFirstSuppressedWaypoint(); + return getInvolvedCompetitors().get(0).getName() + " at mark " + getZeroBasedIndexOfFirstSuppressedWaypoint(); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterCompetitorEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterCompetitorEvent.java index 185a9f226a8..5d526694b96 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterCompetitorEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogRegisterCompetitorEvent.java @@ -4,7 +4,10 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent; -public interface RaceLogRegisterCompetitorEvent extends RaceLogEvent, -RegisterCompetitorEvent { +/** + * ATTENTION: This is the old legacy race log event for a competitor registration from the time before bug2822 + * DON'T delete or rename for backward compatibility + */ +public interface RaceLogRegisterCompetitorEvent extends RaceLogEvent, RegisterCompetitorEvent { } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.java index 460c633d444..fe7e83f5f55 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.java @@ -8,9 +8,6 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; * This is a marker event, which marks a {@link RaceLog} for using it's own boat registrations. When present, * boats are not registered on the RegattaLog corresponding to the RaceLog, but on the RaceLog itself. * - * See bug2851. - * - * @see RaceLogUsesOwnBoatsAnalyzer * @author Frank Mittag * */ diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAnalyzer.java index 95ff17e1784..084d9c7a97a 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAnalyzer.java @@ -6,7 +6,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogAnalyzer; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; /** * Used to find competitors of a race based on {@link RaceLog} and {@link RegattaLog} contents. Checks whether the @@ -20,7 +20,7 @@ import com.sap.sailing.domain.base.Competitor; * @author Jan Bross (D056848) * */ -public class RegisteredCompetitorsAnalyzer extends RaceLogAnalyzer> { +public class RegisteredCompetitorsAnalyzer extends RaceLogAnalyzer> { private RegattaLog regattaLog; public RegisteredCompetitorsAnalyzer(RaceLog raceLog, RegattaLog regattaLog) { @@ -29,8 +29,8 @@ public class RegisteredCompetitorsAnalyzer extends RaceLogAnalyzer performAnalysis() { - final Set result; + protected Set performAnalysis() { + final Set result; if (new RaceLogUsesOwnCompetitorsAnalyzer(getLog()).analyze()) { // get Events from RaceLog result = new CompetitorsInLogAnalyzer<>(getLog()).analyze(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java index a6606a2aae7..c3757c679f5 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RegisteredCompetitorsAndBoatsAnalyzer.java @@ -32,7 +32,7 @@ public class RegisteredCompetitorsAndBoatsAnalyzer extends RaceLogAnalyzer performAnalysis() { final Map result; - if (new RaceLogUsesOwnCompetitorsAnalyzer(getLog()).analyze()) { + if (new RaceLogUsesOwnCompetitorsAndBoatsAnalyzer(getLog()).analyze()) { // get Events from RaceLog result = new CompetitorsAndBoatsInLogAnalyzer<>(getLog()).analyze(); } else { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorAndBoatEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorAndBoatEventImpl.java index 50daed3a0cd..e001d693a51 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorAndBoatEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorAndBoatEventImpl.java @@ -46,7 +46,7 @@ public class RaceLogRegisterCompetitorAndBoatEventImpl extends BaseRegisterCompe } @Override - public List getInvolvedBoats() { + public List getInvolvedCompetitors() { return Collections.singletonList(getCompetitor()); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorEventImpl.java index 1c84b6b429b..9d854e9c160 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorEventImpl.java @@ -11,6 +11,7 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventDataImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.shared.events.impl.BaseRegisterCompetitorEventImpl; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sse.common.TimePoint; public class RaceLogRegisterCompetitorEventImpl extends BaseRegisterCompetitorEventImpl implements @@ -23,7 +24,7 @@ public class RaceLogRegisterCompetitorEventImpl extends BaseRegisterCompetitorEv * if {@code competitor} is null */ public RaceLogRegisterCompetitorEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable id, int passId, Competitor competitor) + AbstractLogEventAuthor author, Serializable id, int passId, CompetitorWithBoat competitor) throws IllegalArgumentException { super(createdAt, logicalTimePoint, author, id, competitor); this.raceLogEventData = new RaceLogEventDataImpl(null, passId); @@ -34,7 +35,7 @@ public class RaceLogRegisterCompetitorEventImpl extends BaseRegisterCompetitorEv * if {@code competitor} is null */ public RaceLogRegisterCompetitorEventImpl(TimePoint logicalTimePoint, - AbstractLogEventAuthor author, int passId, Competitor competitor) + AbstractLogEventAuthor author, int passId, CompetitorWithBoat competitor) throws IllegalArgumentException { this(now(), logicalTimePoint, author, randId(), passId, competitor); } @@ -45,8 +46,8 @@ public class RaceLogRegisterCompetitorEventImpl extends BaseRegisterCompetitorEv } @Override - public List getInvolvedBoats() { - return Collections.singletonList(getCompetitor()); + public List getInvolvedCompetitors() { + return Collections.singletonList((Competitor) getCompetitor()); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java index 86d9f917ecc..6246c0f05d7 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/RegattaLogEventVisitor.java @@ -8,6 +8,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -25,6 +26,8 @@ public interface RegattaLogEventVisitor { void visit(RegattaLogRegisterBoatEvent event); + void visit(RegattaLogRegisterEntryEvent event); + void visit(RegattaLogRegisterCompetitorEvent event); void visit(RegattaLogRegisterCompetitorAndBoatEvent event); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterBoatEvent.java index 2a14d08cf9f..5135c57e4ea 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterBoatEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterBoatEvent.java @@ -1,10 +1,9 @@ package com.sap.sailing.domain.abstractlog.regatta.events; +import com.sap.sailing.domain.abstractlog.Revokable; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; -import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; -import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; - -public interface RegattaLogRegisterBoatEvent extends RegattaLogEvent, -RegisterBoatEvent { +import com.sap.sailing.domain.base.Boat; +public interface RegattaLogRegisterBoatEvent extends RegattaLogEvent, Revokable { + Boat getBoat(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorAndBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorAndBoatEvent.java index 9c39e217079..0f9ba9f3e91 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorAndBoatEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorAndBoatEvent.java @@ -1,9 +1,15 @@ package com.sap.sailing.domain.abstractlog.regatta.events; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorAndBoatEvent; +/** + * Registers a competitor together with a boat for {@link RegattaLog} tracked regattas. + * @author Frank Mittag + * + */ public interface RegattaLogRegisterCompetitorAndBoatEvent extends RegattaLogEvent, RegisterCompetitorAndBoatEvent { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorEvent.java index 4362da82dd3..29374f85624 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterCompetitorEvent.java @@ -4,7 +4,11 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent; -public interface RegattaLogRegisterCompetitorEvent extends RegattaLogEvent, -RegisterCompetitorEvent { +/** + * ATTENTION: This is the old legacy regatta log event for a competitor registration from the time before bug2822 + * DON'T delete or rename for backward compatibility + */ +public interface RegattaLogRegisterCompetitorEvent + extends RegattaLogEvent, RegisterCompetitorEvent { } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterEntryEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterEntryEvent.java new file mode 100644 index 00000000000..c5eee3fe6d7 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogRegisterEntryEvent.java @@ -0,0 +1,15 @@ +package com.sap.sailing.domain.abstractlog.regatta.events; + +import com.sap.sailing.domain.abstractlog.Revokable; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; +import com.sap.sailing.domain.base.Competitor; + +/** + * Registers a single entry for the regatta, the entry can be is used as a competitor for all races or the + * regatta or only for single races + * @author Frank Mittag + * + */ +public interface RegattaLogRegisterEntryEvent extends RegattaLogEvent, Revokable { + Competitor getCompetitor(); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java index 69e959e8b19..20b5c649900 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterBoatEventImpl.java @@ -3,15 +3,16 @@ package com.sap.sailing.domain.abstractlog.regatta.events.impl; import java.io.Serializable; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; -import com.sap.sailing.domain.abstractlog.shared.events.impl.BaseRegisterBoatEventImpl; import com.sap.sailing.domain.base.Boat; import com.sap.sse.common.TimePoint; -public class RegattaLogRegisterBoatEventImpl extends BaseRegisterBoatEventImpl +public class RegattaLogRegisterBoatEventImpl extends AbstractLogEventImpl implements RegattaLogRegisterBoatEvent { private static final long serialVersionUID = -4531928509653259811L; + private final Boat boat; /** * @throws IllegalArgumentException @@ -19,7 +20,9 @@ public class RegattaLogRegisterBoatEventImpl extends BaseRegisterBoatEventImpl @@ -18,7 +18,7 @@ public class RegattaLogRegisterCompetitorEventImpl extends BaseRegisterCompetito * if {@code competitor} is null */ public RegattaLogRegisterCompetitorEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable id, Competitor competitor) throws IllegalArgumentException { + AbstractLogEventAuthor author, Serializable id, CompetitorWithBoat competitor) throws IllegalArgumentException { super(createdAt, logicalTimePoint, author, id, competitor); } @@ -27,7 +27,7 @@ public class RegattaLogRegisterCompetitorEventImpl extends BaseRegisterCompetito * if {@code competitor} is null */ public RegattaLogRegisterCompetitorEventImpl(TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Competitor competitor) throws IllegalArgumentException { + AbstractLogEventAuthor author, CompetitorWithBoat competitor) throws IllegalArgumentException { super(logicalTimePoint, author, competitor); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterEntryEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterEntryEventImpl.java new file mode 100644 index 00000000000..2a3434d6172 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterEntryEventImpl.java @@ -0,0 +1,60 @@ +package com.sap.sailing.domain.abstractlog.regatta.events.impl; + +import java.io.Serializable; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sse.common.TimePoint; + +public class RegattaLogRegisterEntryEventImpl extends AbstractLogEventImpl + implements RegattaLogRegisterEntryEvent { + + private static final long serialVersionUID = 2759139058776278902L; + private Competitor competitor; + + /** + * @throws IllegalArgumentException + * if {@code competitor} is null + */ + public RegattaLogRegisterEntryEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable id, Competitor competitor) throws IllegalArgumentException { + super(createdAt, logicalTimePoint, author, id); + checkCompetitor(competitor); + this.competitor = competitor; + } + + /** + * @throws IllegalArgumentException + * if {@code competitor} is null + */ + public RegattaLogRegisterEntryEventImpl(TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Competitor competitor) throws IllegalArgumentException { + this(now(), logicalTimePoint, author, randId(), competitor); + } + + @Override + public void accept(RegattaLogEventVisitor visitor) { + visitor.visit(this); + } + + private static void checkCompetitor(Competitor competitor) throws IllegalArgumentException { + if (competitor == null) { + throw new IllegalArgumentException("Competitor may not be null"); + } + } + + @Override + public Competitor getCompetitor() { + return competitor; + } + + @Override + public String getShortInfo() { + return "competitor: " + getCompetitor().toString(); + } + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java index 409064f0827..22b4cc9e599 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/BaseRegattaLogEventVisitor.java @@ -9,6 +9,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -39,6 +40,10 @@ public class BaseRegattaLogEventVisitor implements RegattaLogEventVisitor { public void visit(RegattaLogRegisterBoatEvent event) { } + @Override + public void visit(RegattaLogRegisterEntryEvent event) { + } + @Override public void visit(RegattaLogRegisterCompetitorEvent event) { } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java index 7f4ae3f34ca..3a91f6c3e5b 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogEventListener.java @@ -10,6 +10,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMap import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; @@ -42,6 +43,11 @@ public abstract class RegattaLogEventListener implements RegattaLogEventVisitor eventAdded(event); } + @Override + public void visit(RegattaLogRegisterEntryEvent event) { + eventAdded(event); + } + @Override public void visit(RegattaLogRegisterCompetitorEvent event) { eventAdded(event); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatDeregistrator.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogBoatDeregistrator.java similarity index 77% rename from java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatDeregistrator.java rename to java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogBoatDeregistrator.java index 6c66f7e9d86..33cb57dbad8 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatDeregistrator.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogBoatDeregistrator.java @@ -1,4 +1,4 @@ -package com.sap.sailing.domain.abstractlog.shared.analyzing; +package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl; import java.util.HashSet; import java.util.Set; @@ -9,7 +9,7 @@ import com.sap.sailing.domain.abstractlog.AbstractLog; import com.sap.sailing.domain.abstractlog.AbstractLogEvent; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer; -import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.common.abstractlog.NotRevokableException; import com.sap.sse.common.Util; @@ -28,14 +28,14 @@ import com.sap.sse.common.Util; * @author Frank Mittag * */ -public class BoatDeregistrator, EventT extends AbstractLogEvent, VisitorT> +public class RegattaLogBoatDeregistrator, EventT extends AbstractLogEvent, VisitorT> extends BaseLogAnalyzer> { - private static final Logger logger = Logger.getLogger(BoatDeregistrator.class.getName()); + private static final Logger logger = Logger.getLogger(RegattaLogBoatDeregistrator.class.getName()); protected final Iterable boatsToDeregister; private AbstractLogEventAuthor eventAuthor; - public BoatDeregistrator(LogT log, Iterable boatsToDeregister, AbstractLogEventAuthor eventAuthor) { + public RegattaLogBoatDeregistrator(LogT log, Iterable boatsToDeregister, AbstractLogEventAuthor eventAuthor) { super(log); this.boatsToDeregister = boatsToDeregister; this.eventAuthor = eventAuthor; @@ -47,8 +47,8 @@ extends BaseLogAnalyzer> { final HashSet boatSet = new HashSet(); Util.addAll(boatsToDeregister, boatSet); for (EventT event : log.getUnrevokedEventsDescending()) { - if (event instanceof RegisterBoatEvent) { - RegisterBoatEvent registerEvent = (RegisterBoatEvent) event; + if (event instanceof RegattaLogRegisterBoatEvent) { + RegattaLogRegisterBoatEvent registerEvent = (RegattaLogRegisterBoatEvent) event; if (boatSet.contains(registerEvent.getBoat())) { result.add(event); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogBoatsInLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogBoatsInLogAnalyzer.java new file mode 100644 index 00000000000..6969d84ffe3 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogBoatsInLogAnalyzer.java @@ -0,0 +1,38 @@ +package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl; + +import java.util.HashSet; +import java.util.Set; + +import com.sap.sailing.domain.abstractlog.AbstractLog; +import com.sap.sailing.domain.abstractlog.AbstractLogEvent; +import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; +import com.sap.sailing.domain.base.Boat; + +/** + * This class searches for RegisterBoat events in the given log. + * + * Boats alone in a regatta log are not enough to be used in a real race. + * Instead a competitor and a boat together must be registered through a {@link RegisterCompetitorAndBoat} event. + * + */ +public class RegattaLogBoatsInLogAnalyzer, EventT extends AbstractLogEvent, VisitorT> + extends BaseLogAnalyzer> { + + public RegattaLogBoatsInLogAnalyzer(LogT log) { + super(log); + } + + @Override + protected Set performAnalysis() { + Set result = new HashSet(); + + for (EventT event : getLog().getUnrevokedEvents()) { + if (event instanceof RegattaLogRegisterBoatEvent) { + result.add(((RegattaLogRegisterBoatEvent) event).getBoat()); + } + } + + return result; + } +} \ No newline at end of file diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogEntriesInLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogEntriesInLogAnalyzer.java new file mode 100644 index 00000000000..66e7d7cc1b9 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogEntriesInLogAnalyzer.java @@ -0,0 +1,38 @@ +package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl; + +import java.util.HashSet; +import java.util.Set; + +import com.sap.sailing.domain.abstractlog.AbstractLog; +import com.sap.sailing.domain.abstractlog.AbstractLogEvent; +import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; +import com.sap.sailing.domain.base.Competitor; + +/** + * This class searches for RegisterEntry events in the given log. + * + * Entries alone in a regatta log are not enough to be used in a real race. + * Instead an entry (competitor) and a boat together must be registered through a {@link RegisterCompetitorAndBoat} event. + * + */ +public class RegattaLogEntriesInLogAnalyzer, EventT extends AbstractLogEvent, VisitorT> + extends BaseLogAnalyzer> { + + public RegattaLogEntriesInLogAnalyzer(LogT log) { + super(log); + } + + @Override + protected Set performAnalysis() { + Set result = new HashSet(); + + for (EventT event : getLog().getUnrevokedEvents()) { + if (event instanceof RegattaLogRegisterEntryEvent) { + result.add(((RegattaLogRegisterEntryEvent) event).getCompetitor()); + } + } + + return result; + } +} \ No newline at end of file diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatsInLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatsInLogAnalyzer.java deleted file mode 100644 index cc6ff4cebbf..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/BoatsInLogAnalyzer.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.sap.sailing.domain.abstractlog.shared.analyzing; - -import java.util.HashSet; -import java.util.Set; - -import com.sap.sailing.domain.abstractlog.AbstractLog; -import com.sap.sailing.domain.abstractlog.AbstractLogEvent; -import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; -import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; -import com.sap.sailing.domain.base.Boat; - -/** - * This class searches for RegisterBoatsEvents in the given log. - * - * TLDR: It's likely, that you shouldn't use this, but you might want to use {@link RegisteredBoatsAnalyzer} or {@link RaceLogRegisteredBoatsAnalyzer} - * - * Note that solemnly analyzing a certain race or RegattaLog my not lead the correct registered boats for the race - * corresponding to the RaceLog/the races corresponding to the RegattaLog. - * - * This is the case as by default the boats registered on the RegattaLog are used for each race of the regatta - * ignoring the ones in the RaceLog (if present). The RaceLog may override this behavior with the - * {@link RaceLogUseCompetitorsAndBoatsFromRaceLogEvent}. Is an event of this type present, the boats written into the - * RaceLog are used instead of the boats in the RegattaLog. - * - */ -public class BoatsInLogAnalyzer, EventT extends AbstractLogEvent, VisitorT> - extends BaseLogAnalyzer> { - - public BoatsInLogAnalyzer(LogT log) { - super(log); - } - - @Override - protected Set performAnalysis() { - Set result = new HashSet(); - - for (EventT event : getLog().getUnrevokedEvents()) { - if (event instanceof RegisterBoatEvent) { - result.add(((RegisterBoatEvent) event).getBoat()); - } - } - - return result; - } -} \ No newline at end of file diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsInLogAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsInLogAnalyzer.java index 7001fda0406..cbf3c02a0a4 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsInLogAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/analyzing/CompetitorsInLogAnalyzer.java @@ -10,7 +10,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogRegisteredC import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAnalyzer; import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; /** * This class searches for RegisterCompetitorEvents in the given log. @@ -27,15 +27,15 @@ import com.sap.sailing.domain.base.Competitor; * */ public class CompetitorsInLogAnalyzer, EventT extends AbstractLogEvent, VisitorT> - extends BaseLogAnalyzer> { + extends BaseLogAnalyzer> { public CompetitorsInLogAnalyzer(LogT log) { super(log); } @Override - protected Set performAnalysis() { - Set result = new HashSet(); + protected Set performAnalysis() { + Set result = new HashSet<>(); for (EventT event : getLog().getUnrevokedEvents()) { if (event instanceof RegisterCompetitorEvent) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterBoatEvent.java deleted file mode 100644 index 094a20c5d8d..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterBoatEvent.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.sap.sailing.domain.abstractlog.shared.events; - -import com.sap.sailing.domain.abstractlog.AbstractLogEvent; -import com.sap.sailing.domain.abstractlog.Revokable; -import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; -import com.sap.sailing.domain.base.Boat; -import com.sap.sse.common.IsManagedByCache; - -/** - * Register a boat for {@link RaceLog} and {@link RegattaLog} tracked races and regattas. - * - * A dummy {@link Boat} implementation with only an {@link Boat#getId() id} may be used, - * if the boat is known to already exist on the server, as it is - * {@link IsManagedByCache#resolve(com.sap.sailing.domain.base.SharedDomainFactory) resolved} - * on arrival. - * @author Frank Mittag - * - */ -public interface RegisterBoatEvent extends AbstractLogEvent, Revokable { - Boat getBoat(); -} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java index f1fb754ec8b..31fddb958a3 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorAndBoatEvent.java @@ -1,12 +1,15 @@ package com.sap.sailing.domain.abstractlog.shared.events; +import com.sap.sailing.domain.abstractlog.AbstractLogEvent; +import com.sap.sailing.domain.abstractlog.Revokable; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.IsManagedByCache; /** - * Register a competitor together with a boat for {@link RaceLog} and {@link RegattaLog} trackeds race and regattas. + * Register a competitor together with a boat for {@link RaceLog} and {@link RegattaLog} tracked races and regattas. * * A dummy {@link Competitor} implementation with only an {@link Competitor#getId() id} may be used, * if the competitor is known to already exist on the server, as it is @@ -15,5 +18,8 @@ import com.sap.sse.common.IsManagedByCache; * @author Frank Mittag * */ -public interface RegisterCompetitorAndBoatEvent extends RegisterBoatEvent, RegisterCompetitorEvent { +public interface RegisterCompetitorAndBoatEvent extends AbstractLogEvent, Revokable { + Competitor getCompetitor(); + + Boat getBoat(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorEvent.java index 95897699c6c..66f6de6c905 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/RegisterCompetitorEvent.java @@ -5,9 +5,13 @@ import com.sap.sailing.domain.abstractlog.Revokable; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sse.common.IsManagedByCache; /** + * ATTENTION: This is the old legacy log event for a competitor registration from the time before bug2822 + * DON'T delete or rename for backward compatibility + * * Register a competitor for {@link RaceLog} and {@link RegattaLog} tracked races and regattas. * * A dummy {@link Competitor} implementation with only an {@link Competitor#getId() id} may be used, @@ -18,5 +22,5 @@ import com.sap.sse.common.IsManagedByCache; * */ public interface RegisterCompetitorEvent extends AbstractLogEvent, Revokable { - Competitor getCompetitor(); + CompetitorWithBoat getCompetitor(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterBoatEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterBoatEventImpl.java deleted file mode 100644 index 8e57146971f..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterBoatEventImpl.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.sap.sailing.domain.abstractlog.shared.events.impl; - -import java.io.Serializable; - -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl; -import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; -import com.sap.sailing.domain.base.Boat; -import com.sap.sse.common.TimePoint; - -public abstract class BaseRegisterBoatEventImpl extends AbstractLogEventImpl implements - RegisterBoatEvent { - private static final long serialVersionUID = -224096196692372694L; - private final Boat boat; - - /** - * @throws IllegalArgumentException - * if {@code boat} is null - */ - public BaseRegisterBoatEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable pId, Boat boat) throws IllegalArgumentException { - super(createdAt, logicalTimePoint, author, pId); - checkBoat(boat); - this.boat = boat; - } - - /** - * @throws IllegalArgumentException - * if {@code boat} is null - */ - public BaseRegisterBoatEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Boat boat) throws IllegalArgumentException { - this(now(), logicalTimePoint, author, randId(), boat); - } - - private static void checkBoat(Boat boat) throws IllegalArgumentException { - if (boat == null) { - throw new IllegalArgumentException("Boat may not be null"); - } - } - - @Override - public Boat getBoat() { - return boat; - } - - @Override - public String getShortInfo() { - return "boat: " + getBoat().toString(); - } -} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorEventImpl.java index ac71017500e..d317da64a5e 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorEventImpl.java @@ -5,20 +5,20 @@ import java.io.Serializable; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.AbstractLogEventImpl; import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sse.common.TimePoint; public abstract class BaseRegisterCompetitorEventImpl extends AbstractLogEventImpl implements RegisterCompetitorEvent { private static final long serialVersionUID = -30864810737555657L; - private final Competitor competitor; + private final CompetitorWithBoat competitor; /** * @throws IllegalArgumentException * if {@code competitor} is null */ public BaseRegisterCompetitorEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable pId, Competitor competitor) throws IllegalArgumentException { + AbstractLogEventAuthor author, Serializable pId, CompetitorWithBoat competitor) throws IllegalArgumentException { super(createdAt, logicalTimePoint, author, pId); checkCompetitor(competitor); this.competitor = competitor; @@ -29,18 +29,21 @@ public abstract class BaseRegisterCompetitorEventImpl extends Abstract * if {@code competitor} is null */ public BaseRegisterCompetitorEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Competitor competitor) throws IllegalArgumentException { + CompetitorWithBoat competitor) throws IllegalArgumentException { this(now(), logicalTimePoint, author, randId(), competitor); } - private static void checkCompetitor(Competitor competitor) throws IllegalArgumentException { + private static void checkCompetitor(CompetitorWithBoat competitor) throws IllegalArgumentException { if (competitor == null) { throw new IllegalArgumentException("Competitor may not be null"); } + if (competitor.getBoat() == null) { + throw new IllegalArgumentException("BoaCompetitor may not be null"); + } } @Override - public Competitor getCompetitor() { + public CompetitorWithBoat getCompetitor() { return competitor; } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java index 47e24499e51..b6ccfbe10ed 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorStore.java @@ -12,17 +12,21 @@ import com.sap.sse.common.Color; import com.sap.sse.common.Duration; /** - * Manages a set of {@link Competitor} and {@link Boat} objects. There may be a transient implementation based on a simple cache, + * Manages a set of {@link Competitor}, {@link CompetitorWithBoat} and {@link Boat} objects. There may be a transient implementation based on a simple cache, * and there may be persistent implementations. * * @author Axel Uhl (d043530) * */ -public interface CompetitorStore extends CompetitorFactory, BoatFactory { +public interface CompetitorStore extends CompetitorFactory, BoatFactory, CompetitorWithBoatFactory { public interface CompetitorUpdateListener { void competitorUpdated(Competitor competitor); } + public interface CompetitorWithBoatUpdateListener { + void competitorWithBoatUpdated(CompetitorWithBoat competitorWithBoat); + } + public interface BoatUpdateListener { void boatUpdated(Boat boat); } @@ -36,14 +40,14 @@ public interface CompetitorStore extends CompetitorFactory, BoatFactory { Competitor getExistingCompetitorByIdAsString(String idAsString); /** - * When a competitor is queried using {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} + * When a competitor is queried using {@link #getOrCreateCompetitor()} * , and the competitor object for that ID already exists, it is generally returned unchanged, and the name, team * and boat parameters are not evaluated. This makes the data in this competitor store generally "write-once." This * method can be used to reset a competitor object to what a tracking provider or an external system supplies to - * {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)}. After calling this method, the - * next call to {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} with + * {@link #getOrCreateCompetitor()}. After calling this method, the + * next call to {@link #getOrCreateCompetitor()} with * competitor's {@link Competitor#getId() ID} will - * {@link #updateCompetitor(String, String, String, Nationality)} the competitor in its updatable properties such as + * {@link #updateCompetitor()} the competitor in its updatable properties such as * the name, the sail ID and the nationality. */ void allowCompetitorResetToDefaults(Competitor competitor); @@ -78,8 +82,6 @@ public interface CompetitorStore extends CompetitorFactory, BoatFactory { CompetitorWithoutBoatDTO convertToCompetitorWithoutBoatDTO(Competitor c); - CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat c); - CompetitorDTO convertToCompetitorDTO(Competitor c, Boat b); /** @@ -90,6 +92,63 @@ public interface CompetitorStore extends CompetitorFactory, BoatFactory { void removeCompetitorUpdateListener(CompetitorUpdateListener listener); + /** + * If a valid competitor is returned and the caller has information available that could be used to update the competitor, + * the caller must check the result of {@link #isCompetitorWithBoatToUpdateDuringGetOrCreate(CompetitorWithBoat)}, and if true, + * must call {@link #getOrCreateCompetitorWithBoat()} to cause an update of the competitor's values. + */ + CompetitorWithBoat getExistingCompetitorWithBoatByIdAsString(String idAsString); + + /** + * When a competitor is queried using {@link #getOrCreateCompetitorWithBoat()} + * and the competitorWithBoat object for that ID already exists, it is generally returned unchanged, and the name, team + * and boat parameters are not evaluated. This makes the data in this competitor store generally "write-once." This + * method can be used to reset a competitorWithBoat object to what a tracking provider or an external system supplies to + * {@link #getOrCreateCompetitorWithBoat()}. After calling this method, the + * next call to {@link #getOrCreateCompetitorWithBoat()} with competitor's {@link CompetitorWithBoat#getId() ID} will + * {@link #updateCompetitorWithBoat()} the competitorWithBoat in its updatable properties such as + * the name, the sail ID and the nationality. + */ + void allowCompetitorWithBoatResetToDefaults(CompetitorWithBoat competitor); + + int getCompetitorsWithBoatCount(); + + /** + * Removes all competitors from this store. Use with due care. + */ + void clearCompetitorsWithBoat(); + + /** + * Obtains a non-live snapshot of the list of competitors managed by this store. + */ + Iterable getCompetitorsWithBoat(); + + void removeCompetitorWithBoat(CompetitorWithBoat competitor); + + /** + * Updates the competitor with {@link Competitor#getId() ID} id by setting the name, sail ID and nationality to + * the values provided. Doing so will not fire any events nor will it replicate this change from a master to any replicas. + * The calling client has to make sure that the changes applied will reach replicas and all other interested clients. It will + * be sufficient to ensure that subsequent DTOs produced from the competitor modified will reflect the changes.

+ * + * If no competitor with the ID requested is found, the call is a no-op, doing nothing, not even throwing an exception. + */ + CompetitorWithBoat updateCompetitorWithBoat(String idAsString, String newName, String newShortName, Color newDisplayColor, String newEmail, + Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, + Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag); + + void addCompetitorsWithBoat(Iterable competitors); + + CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat c); + + /** + * Listeners added here are notified whenever {@link #updateCompetitorWithBoat()} is called + * for any competitor in this store. + */ + void addCompetitorWithBoatUpdateListener(CompetitorWithBoatUpdateListener listener); + + void removeCompetitorWithBoatUpdateListener(CompetitorWithBoatUpdateListener listener); + /** * If a valid boat is returned and the caller has information available that could be used to update the boat, * the caller must check the result of {@link #isBoatToUpdateDuringGetOrCreate(Competitor)}, and if true, @@ -122,6 +181,8 @@ public interface CompetitorStore extends CompetitorFactory, BoatFactory { void removeBoat(Boat boat); + void migrateCompetitorToHaveASeparateBoat(Competitor existingCompetitor, Boat separateBoat); + /** * Updates the boat with {@link Boat#getId() ID} id by setting the name, sail ID, etc. to * the values provided. Doing so will not fire any events nor will it replicate this change from a master to any replicas. diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoatFactory.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoatFactory.java new file mode 100644 index 00000000000..7fcf35461af --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/CompetitorWithBoatFactory.java @@ -0,0 +1,33 @@ +package com.sap.sailing.domain.base; + +import java.io.Serializable; +import java.net.URI; + +import com.sap.sailing.domain.base.impl.DynamicBoat; +import com.sap.sailing.domain.base.impl.DynamicTeam; +import com.sap.sse.common.Color; +import com.sap.sse.common.Duration; + +/** + * Base interface for classes managing a set of {@link Competitor} objects which contain a {@link Boat} object belonging to the competitor. + */ +public interface CompetitorWithBoatFactory { + /** + * If a valid competitor is returned and the caller has information available that could be used to update the competitor, + * the caller must check the result of {@link #isCompetitorWithBoatToUpdateDuringGetOrCreate(Competitor)}, and if true, + * must call {@link #getOrCreateCompetitorWithBoat(Serializable, String, DynamicTeam, DynamicBoat)} to cause an update of the + * competitor's values. + */ + CompetitorWithBoat getExistingCompetitorWithBoatById(Serializable competitorWithBoatId); + + /** + * Checks if the competitor shall be updated from the default provided by, e.g., a tracking infrastructure. + * Callers of {@link #getExistingCompetitorWithBoatById(Serializable)} or {@link #getExistingCompetitorWithBoatByIdAsString(String)} + * must call this method in case they retrieve a valid competitor by ID and have data available that can be used to update + * the competitor. + */ + boolean isCompetitorWithBoatToUpdateDuringGetOrCreate(CompetitorWithBoat result); + + CompetitorWithBoat getOrCreateCompetitorWithBoat(Serializable competitorId, String name, String shortName, Color displayColor, String email, + URI flagImageURI, DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag, DynamicBoat boat); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java index f2c9fa6aeaf..e0c3f5ca9d7 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/SharedDomainFactory.java @@ -10,7 +10,7 @@ import com.sap.sailing.domain.common.MarkType; import com.sap.sailing.domain.common.PassingInstruction; import com.sap.sse.common.Color; -public interface SharedDomainFactory extends CompetitorFactory, BoatFactory { +public interface SharedDomainFactory extends CompetitorFactory, CompetitorWithBoatFactory, BoatFactory { /** * Looks up or, if not found, creates a {@link Nationality} object and re-uses threeLetterIOCCode also as the diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java index e137a34e322..37412b9d057 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/CompetitorWithBoatImpl.java @@ -3,32 +3,30 @@ package com.sap.sailing.domain.base.impl; import java.io.Serializable; import java.net.URI; -import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sse.common.Color; import com.sap.sse.common.Duration; -public class CompetitorWithBoatImpl extends CompetitorImpl implements CompetitorWithBoat { +public class CompetitorWithBoatImpl extends CompetitorImpl implements DynamicCompetitorWithBoat { private static final long serialVersionUID = 22679449208503264L; - private final Boat boat; + private final DynamicBoat boat; public CompetitorWithBoatImpl(Serializable id, String name, String shortName, Color color, String email, URI flagImage, DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, - String searchTag, Boat boat) { + String searchTag, DynamicBoat boat) { super(id, name, shortName, color, email, flagImage, team, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); this.boat = boat; } - public CompetitorWithBoatImpl(Competitor competitor, Boat boat) { + public CompetitorWithBoatImpl(Competitor competitor, DynamicBoat boat) { this(competitor.getId(), competitor.getName(), competitor.getShortName(), competitor.getColor(), competitor.getEmail(), competitor.getFlagImage(), (DynamicTeam) competitor.getTeam(), competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag(), boat); } @Override - public Boat getBoat() { + public DynamicBoat getBoat() { return boat; } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitorWithBoat.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitorWithBoat.java new file mode 100644 index 00000000000..4771f8b6067 --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/DynamicCompetitorWithBoat.java @@ -0,0 +1,7 @@ +package com.sap.sailing.domain.base.impl; + +import com.sap.sailing.domain.base.CompetitorWithBoat; + +public interface DynamicCompetitorWithBoat extends DynamicCompetitor, CompetitorWithBoat { + DynamicBoat getBoat(); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java index 6721043876d..429a06a965d 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java @@ -20,6 +20,7 @@ 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.CompetitorStore; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.ControlPoint; import com.sap.sailing.domain.base.ControlPointWithTwoMarks; import com.sap.sailing.domain.base.CourseArea; @@ -342,6 +343,11 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { return getCompetitorStore().getExistingCompetitorById(competitorId); } + @Override + public CompetitorWithBoat getExistingCompetitorWithBoatById(Serializable competitorId) { + return getCompetitorStore().getExistingCompetitorWithBoatById(competitorId); + } + @Override public boolean isCompetitorToUpdateDuringGetOrCreate(Competitor competitor) { return getCompetitorStore().isCompetitorToUpdateDuringGetOrCreate(competitor); @@ -358,6 +364,17 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); } + @Override + public CompetitorWithBoat getOrCreateCompetitorWithBoat(Serializable competitorId, String name, String shortName, + Color displayColor, String email, URI flagImageURI, DynamicTeam team, Double timeOnTimeFactor, + Duration timeOnDistanceAllowancePerNauticalMile, String searchTag, DynamicBoat boat) { + if (logger.isLoggable(Level.FINEST)) { + logger.log(Level.FINEST, "getting or creating competitor "+name+" with ID "+competitorId+" in domain factory "+this); + } + return getCompetitorStore().getOrCreateCompetitorWithBoat(competitorId, name, shortName, displayColor, email, flagImageURI, team, + timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag, boat); + } + @Override public Boat getExistingBoatById(Serializable boatId) { return getCompetitorStore().getExistingBoatById(boatId); @@ -368,6 +385,11 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { return getCompetitorStore().isBoatToUpdateDuringGetOrCreate(boat); } + @Override + public boolean isCompetitorWithBoatToUpdateDuringGetOrCreate(CompetitorWithBoat competitor) { + return getCompetitorStore().isCompetitorWithBoatToUpdateDuringGetOrCreate(competitor); + } + @Override public Boat getOrCreateBoat(Serializable id, String name, BoatClass boatClass, String sailId, Color color) { return getCompetitorStore().getOrCreateBoat(id, name, boatClass, sailId, color); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index 7b12a82791e..d9ffd133122 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -36,22 +36,35 @@ import com.sap.sse.concurrent.NamedReentrantReadWriteLock; public class TransientCompetitorStoreImpl implements CompetitorStore, Serializable { private static final Logger logger = Logger.getLogger(TransientCompetitorStoreImpl.class.getName()); private static final long serialVersionUID = -4198298775476586931L; + private final Map competitorCache; private final Map competitorsByIdAsString; private transient Set competitorUpdateListeners; + + private final Map competitorWithBoatCache; + private final Map competitorsWithBoatByIdAsString; + private transient Set competitorWithBoatUpdateListeners; + private final Map boatCache; private final Map boatsByIdAsString; private transient Set boatUpdateListeners; /** * The competitors contained in this map will have their changeable properties - * {@link #updateCompetitor(String, String, String, Nationality) updated} upon the next call to - * {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} for their ID. + * {@link #updateCompetitor() updated} upon the next call to {@link #getOrCreateCompetitor()} for their ID. */ private final Set competitorsToUpdateDuringGetOrCreate; private transient WeakHashMap weakCompetitorDTOCache; + /** + * The competitors contained in this map will have their changeable properties + * {@link #updateCompetitor() updated} upon the next call to {@link #getOrCreateCompetitor()} for their ID. + */ + private final Set competitorsWithBoatToUpdateDuringGetOrCreate; + + private transient WeakHashMap weakCompetitorWithBoatDTOCache; + private final Set boatsToUpdateDuringGetOrCreate; private transient WeakHashMap weakBoatDTOCache; @@ -65,6 +78,13 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab competitorsToUpdateDuringGetOrCreate = new HashSet(); weakCompetitorDTOCache = new WeakHashMap(); competitorUpdateListeners = Collections.synchronizedSet(new HashSet()); + + competitorWithBoatCache = new HashMap(); + competitorsWithBoatByIdAsString = new HashMap(); + competitorsWithBoatToUpdateDuringGetOrCreate = new HashSet(); + weakCompetitorWithBoatDTOCache = new WeakHashMap(); + competitorWithBoatUpdateListeners = Collections.synchronizedSet(new HashSet()); + boatCache = new HashMap(); boatsByIdAsString = new HashMap(); boatsToUpdateDuringGetOrCreate = new HashSet(); @@ -76,6 +96,8 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab ois.defaultReadObject(); weakCompetitorDTOCache = new WeakHashMap(); competitorUpdateListeners = Collections.synchronizedSet(new HashSet()); + weakCompetitorWithBoatDTOCache = new WeakHashMap(); + competitorWithBoatUpdateListeners = Collections.synchronizedSet(new HashSet()); weakBoatDTOCache = new WeakHashMap(); boatUpdateListeners = Collections.synchronizedSet(new HashSet()); } @@ -101,6 +123,11 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab return result; } + @Override + public void migrateCompetitorToHaveASeparateBoat(Competitor existingCompetitor, Boat separateBoat) { + addNewBoat(separateBoat.getId(), separateBoat); + } + /** * Adds the competitor to this transient competitor collection so that it is available in * {@link #getExistingCompetitorById(Serializable)}. Subclasses may override in case they need to take additional @@ -281,11 +308,6 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab } } } - - @Override - public CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat competitorWithBoat) { - return convertToCompetitorDTO(competitorWithBoat, competitorWithBoat.getBoat()); - } @Override public CompetitorDTO convertToCompetitorDTO(Competitor competitor, Boat boat) { @@ -328,6 +350,204 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab } } + /** CompetitorWithBoat stuff starts here */ + + @Override + public void addCompetitorWithBoatUpdateListener(CompetitorWithBoatUpdateListener listener) { + competitorWithBoatUpdateListeners.add(listener); + } + + @Override + public void removeCompetitorWithBoatUpdateListener(CompetitorWithBoatUpdateListener listener) { + competitorWithBoatUpdateListeners.remove(listener); + } + + private CompetitorWithBoat createCompetitorWithBoat(Serializable id, String name, String shortName, Color displayColor, String email, URI flagImage, + DynamicTeam team, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String searchTag, DynamicBoat boat) { + CompetitorWithBoat result = new CompetitorWithBoatImpl(id, name, shortName, displayColor, email, flagImage, team, + timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag, boat); + addNewCompetitorWithBoat(id, result); + if (logger.isLoggable(Level.FINEST)) { + logger.log(Level.FINEST, "Created competitor "+name+" with ID "+id, new Exception("Here is where it happened")); + } + return result; + } + + /** + * Adds the competitor to this transient competitor collection so that it is available in + * {@link #getExistingCompetitorById(Serializable)}. Subclasses may override in case they need to take additional + * measures such as durably storing the competitor. Overriding implementations must call this implementation. + */ + protected void addNewCompetitorWithBoat(Serializable id, CompetitorWithBoat competitor) { + LockUtil.lockForWrite(lock); + try { + competitorWithBoatCache.put(id, competitor); + competitorsWithBoatByIdAsString.put(id.toString(), competitor); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public CompetitorWithBoat getOrCreateCompetitorWithBoat(Serializable competitorId, String name, String shortName, Color displayColor, String email, + URI flagImage, DynamicTeam team, Double timeOnTimeFactor, + Duration timeOnDistanceAllowancePerNauticalMile, String searchTag, DynamicBoat boat) { + CompetitorWithBoat result = getExistingCompetitorWithBoatById(competitorId); // avoid synchronization for successful read access + if (result == null) { + LockUtil.lockForWrite(lock); + try { + result = getExistingCompetitorWithBoatById(competitorId); // try again, now while holding the write lock + if (result == null) { + result = createCompetitorWithBoat(competitorId, name, shortName, displayColor, email, flagImage, team, + timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag, boat); + } + } finally { + LockUtil.unlockAfterWrite(lock); + } + } else if (isCompetitorWithBoatToUpdateDuringGetOrCreate(result)) { + updateCompetitorWithBoat(result.getId().toString(), name, shortName, displayColor, email, team.getNationality(), + team.getImage(), flagImage, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); + competitorWithBoatNoLongerToUpdateDuringGetOrCreate(result); + } + return result; + } + + private void competitorWithBoatNoLongerToUpdateDuringGetOrCreate(CompetitorWithBoat competitor) { + competitorsWithBoatToUpdateDuringGetOrCreate.remove(competitor); + } + + @Override + public boolean isCompetitorWithBoatToUpdateDuringGetOrCreate(CompetitorWithBoat competitor) { + return competitorsWithBoatToUpdateDuringGetOrCreate.contains(competitor); + } + + @Override + public CompetitorWithBoat getExistingCompetitorWithBoatById(Serializable competitorWithBoatId) { + LockUtil.lockForRead(lock); + try { + return competitorWithBoatCache.get(competitorWithBoatId); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public CompetitorWithBoat getExistingCompetitorWithBoatByIdAsString(String competitorWithBoatIdAsString) { + LockUtil.lockForRead(lock); + try { + return competitorsWithBoatByIdAsString.get(competitorWithBoatIdAsString); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public int getCompetitorsWithBoatCount() { + LockUtil.lockForRead(lock); + try { + return competitorWithBoatCache.size(); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public void clearCompetitorsWithBoat() { + LockUtil.lockForWrite(lock); + try { + competitorWithBoatCache.clear(); + competitorsWithBoatByIdAsString.clear(); + competitorsWithBoatToUpdateDuringGetOrCreate.clear(); + if (logger.isLoggable(Level.FINEST)) { + logger.log(Level.FINEST, "Clearing competitorWithBoat store "+this, new Exception("here is where it happened")); + } + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public Iterable getCompetitorsWithBoat() { + LockUtil.lockForRead(lock); + try { + return new ArrayList(competitorWithBoatCache.values()); + } finally { + LockUtil.unlockAfterRead(lock); + } + } + + @Override + public void removeCompetitorWithBoat(CompetitorWithBoat competitor) { + LockUtil.lockForWrite(lock); + try { + logger.fine("removing competitor "+competitor+" from competitor store "+this); + competitorWithBoatCache.remove(competitor.getId()); + competitorsWithBoatByIdAsString.remove(competitor.getId().toString()); + weakCompetitorWithBoatDTOCache.remove(competitor); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public CompetitorWithBoat updateCompetitorWithBoat(String idAsString, String newName, String newShortName, Color newDisplayColor, String newEmail, + Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, + Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, String newSearchTag) { + DynamicCompetitorWithBoat competitor = (DynamicCompetitorWithBoat) getExistingCompetitorWithBoatByIdAsString(idAsString); + if (competitor != null) { + LockUtil.lockForWrite(lock); + try { + competitor.setName(newName); + competitor.setShortName(newShortName); + competitor.setColor(newDisplayColor); + competitor.setEmail(newEmail); + competitor.setFlagImage(newFlagImageUri); + competitor.getTeam().setNationality(newNationality); + competitor.getTeam().setImage(newTeamImageUri); + competitor.setTimeOnTimeFactor(timeOnTimeFactor); + competitor.setTimeOnDistanceAllowancePerNauticalMile(timeOnDistanceAllowancePerNauticalMile); + competitor.setSearchTag(newSearchTag); + weakCompetitorDTOCache.remove(competitor); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + synchronized (competitorUpdateListeners) { + for (CompetitorUpdateListener listener : competitorUpdateListeners) { + listener.competitorUpdated(competitor); + } + } + return (CompetitorWithBoat) competitor; + } + + @Override + public CompetitorDTO convertToCompetitorDTO(CompetitorWithBoat competitorWithBoat) { + return convertToCompetitorDTO(competitorWithBoat, competitorWithBoat.getBoat()); + } + + @Override + public void allowCompetitorWithBoatResetToDefaults(CompetitorWithBoat competitor) { + LockUtil.lockForWrite(lock); + try { + competitorsWithBoatToUpdateDuringGetOrCreate.add(competitor); + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + + @Override + public void addCompetitorsWithBoat(Iterable competitors) { + LockUtil.lockForWrite(lock); + try { + for (CompetitorWithBoat competitor: competitors) { + competitorWithBoatCache.put(competitor.getId(), competitor); + competitorsWithBoatByIdAsString.put(competitor.getId().toString(), competitor); + } + } finally { + LockUtil.unlockAfterWrite(lock); + } + } + /** Boat stuff starts here */ @Override diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java index 3e84daed991..303a1649001 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractLeaderboardTest.java @@ -1,17 +1,18 @@ package com.sap.sailing.domain.test; -import java.io.Serializable; import java.util.Collections; 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.CompetitorFactory; import com.sap.sailing.domain.base.CompetitorAndBoat; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.base.impl.PersonImpl; import com.sap.sailing.domain.base.impl.TeamImpl; @@ -21,35 +22,29 @@ public abstract class AbstractLeaderboardTest { private final static BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); public static CompetitorAndBoat createCompetitorAndBoat(String competitorName) { - Competitor c = new CompetitorImpl(competitorName, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + return new CompetitorAndBoatImpl(createCompetitor(competitorName), createBoat(competitorName)); + } + + public static Competitor createCompetitor(String competitorName) { + return new CompetitorImpl(competitorName, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */null, "This is Rigo, the coach")), - /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - Boat b = new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); - return new CompetitorAndBoatImpl(c, b); + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, /* searchTag */ null); } - public static CompetitorAndBoat createCompetitorAndBoat(String competitorName, CompetitorFactory competitorFactory) { - Competitor c = competitorFactory.getOrCreateCompetitor(competitorName, competitorName, "WH", Color.RED, "someone@nobody.de", null, new TeamImpl("STG", Collections.singleton( - new PersonImpl(competitorName, new NationalityImpl("GER"), - /* dateOfBirth */ null, "This is famous "+competitorName)), - new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), - /* dateOfBirth */null, "This is Rigo, the coach")), - /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null); - Boat b = new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); - return new CompetitorAndBoatImpl(c, b); + public static Boat createBoat(String competitorName) { + return new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); } - public static CompetitorAndBoat createCompetitorAndBoat(String competitorName, Serializable id) { - Competitor c = new CompetitorImpl(id, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + public static CompetitorWithBoat createCompetitorWithBoat(String competitorName) { + DynamicBoat b = (DynamicBoat) createBoat(competitorName); + return new CompetitorWithBoatImpl(competitorName, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( new PersonImpl(competitorName, new NationalityImpl("GER"), /* dateOfBirth */ null, "This is famous "+competitorName)), new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), /* dateOfBirth */null, "This is Rigo, the coach")), - /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); - Boat b = new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); - return new CompetitorAndBoatImpl(c, b); + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, /* searchTag */ null, b); } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java index 63bddb6eee3..964f1b1a615 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java @@ -19,12 +19,14 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorAndBoatEventImpl; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.base.impl.BoatClassImpl; @@ -49,7 +51,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; /** * Tests the behavior of the class {@link CompetitorProviderFromRaceColumnsAndRegattaLike}, paying particular - * attention to its caching and cache invalidation logic. When competitors are added to regatta logs or race logs + * attention to its caching and cache invalidation logic. When competitors and their boats are added to regatta logs or race logs * or when a tracked race is attached to a column or a column is added or removed, its caches need to be * invalidated and re-calculated accordingly. * @@ -65,6 +67,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard final int NUMBER_OF_COMP_LISTS = 4; @SuppressWarnings("unchecked") private List[] compLists = (List[]) new List[NUMBER_OF_COMP_LISTS]; + private Map boats = new HashMap<>(); @Before public void setUp() { @@ -84,7 +87,9 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard for (int l = 0; l < NUMBER_OF_COMP_LISTS; l++) { compLists[l] = new ArrayList(); for (int i = 0; i < 10; i++) { - compLists[l].add(createCompetitorAndBoat("" + l + "/" + i).getCompetitor()); + Competitor c = createCompetitor("" + l + "/" + i); + compLists[l].add(c); + boats.put(c, createBoat("" + l + "/" + i)); } } competitorProviderRegattaLeaderboard = new CompetitorProviderFromRaceColumnsAndRegattaLike(regattaLeaderboard); @@ -100,10 +105,10 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard regatta.removeSeries(seriesToRemove); } RegattaLog regattaLog = regattaLeaderboard.getRegatta().getRegattaLog(); - final Map competitorOnRegattaLogRegistrationEvents = new HashMap<>(); + final Map competitorOnRegattaLogRegistrationEvents = new HashMap<>(); final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0); for (Competitor c : compLists[0]) { - final RegattaLogRegisterCompetitorEventImpl registerCompetitorEvent = new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), c); + final RegattaLogRegisterCompetitorAndBoatEvent registerCompetitorEvent = new RegattaLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), c, boats.get(c)); regattaLog.add(registerCompetitorEvent); competitorOnRegattaLogRegistrationEvents.put(c, registerCompetitorEvent); } @@ -137,10 +142,10 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard RaceLog raceLog = flexibleLeaderboard.getRacelog("R1", LeaderboardNameConstants.DEFAULT_FLEET_NAME); final int passId = 1; final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0); - raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); - final Map competitorOnRaceLogRegistrationEvents = new HashMap<>(); + raceLog.add(new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); + final Map competitorOnRaceLogRegistrationEvents = new HashMap<>(); for (Competitor c : compLists[0]) { - final RaceLogRegisterCompetitorEvent registerCompetitorEvent = new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, passId, c); + final RaceLogRegisterCompetitorAndBoatEvent registerCompetitorEvent = new RaceLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), author, passId, c, boats.get(c)); raceLog.add(registerCompetitorEvent); competitorOnRaceLogRegistrationEvents.put(c, registerCompetitorEvent); } @@ -180,7 +185,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard flexibleLeaderboard.addRaceColumn("R1", /* medalRace */ false); RegattaLog regattaLog = flexibleLeaderboard.getRegattaLog(); for (Competitor c : compLists[0]) { - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), UUID.randomUUID(), c)); + regattaLog.add(new RegattaLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), UUID.randomUUID(), c, boats.get(c))); } Set expected = new HashSet<>(compLists[0]); Set actual = new HashSet<>(); @@ -198,15 +203,15 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard flexibleLeaderboard.addRaceColumn("R1", /* medalRace */ false); RegattaLog regattaLog = flexibleLeaderboard.getRegattaLog(); for (Competitor c : compLists[0]) { - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), UUID.randomUUID(), c)); + regattaLog.add(new RegattaLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), UUID.randomUUID(), c, boats.get(c))); } RaceLog raceLog = flexibleLeaderboard.getRacelog("R1", LeaderboardNameConstants.DEFAULT_FLEET_NAME); final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0); int passId = 1; - final RaceLogUseCompetitorsFromRaceLogEventImpl usesCompetitorsFromRaceLogEvent = new RaceLogUseCompetitorsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId); + final RaceLogUseCompetitorsAndBoatsFromRaceLogEvent usesCompetitorsFromRaceLogEvent = new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId); raceLog.add(usesCompetitorsFromRaceLogEvent); for (Competitor c : compLists[1]) { - raceLog.add(new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c)); + raceLog.add(new RaceLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c, boats.get(c))); } // expected are only the competitors in the RaceLog, because only one RaceColumn is // registered, which has the competitors registered in the RaceLog. @@ -217,7 +222,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard raceLog.revokeEvent(author, usesCompetitorsFromRaceLogEvent); assertRegattaAndRaceCompetitors(new HashSet<>(compLists[0])); // And now re-introduce per-race competitors and validate again that the cache adjusts properly: - raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); + raceLog.add(new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); assertRegattaAndRaceCompetitors(new HashSet<>(compLists[1])); } @@ -302,9 +307,9 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard RaceLog raceLog = regattaLeaderboard.getRacelog("R1", "Yellow"); final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0); int passId = 1; - raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); + raceLog.add(new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); for (Competitor c : compLists[0]) { - raceLog.add(new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c)); + raceLog.add(new RaceLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c, boats.get(c))); } Set expected = new HashSet<>(compLists[0]); Set actual = new HashSet<>(); @@ -319,10 +324,10 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard @Test public void testSimpleCompetitorListOnRegattaLogInRegattaLeaderboard() throws NotRevokableException { RegattaLog regattaLog = regattaLeaderboard.getRegatta().getRegattaLog(); - final Map competitorOnRegattaLogRegistrationEvents = new HashMap<>(); + final Map competitorOnRegattaLogRegistrationEvents = new HashMap<>(); final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0); for (Competitor c : compLists[0]) { - final RegattaLogRegisterCompetitorEventImpl registerCompetitorEvent = new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), c); + final RegattaLogRegisterCompetitorAndBoatEvent registerCompetitorEvent = new RegattaLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), c, boats.get(c)); regattaLog.add(registerCompetitorEvent); competitorOnRegattaLogRegistrationEvents.put(c, registerCompetitorEvent); } @@ -355,14 +360,14 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard final RegattaLog regattaLog = regattaLeaderboard.getRegatta().getRegattaLog(); final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0); for (Competitor c : compLists[0]) { - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), c)); + regattaLog.add(new RegattaLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), c, boats.get(c))); } final RaceLog raceLog = regattaLeaderboard.getRacelog("R1", "Yellow"); final int passId = 1; - raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); - final Map competitorOnRaceLogRegistrationEvents = new HashMap<>(); + raceLog.add(new RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), passId)); + final Map competitorOnRaceLogRegistrationEvents = new HashMap<>(); for (Competitor c : compLists[passId]) { - final RaceLogRegisterCompetitorEvent registerCompetitorEvent = new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, passId, c); + final RaceLogRegisterCompetitorAndBoatEvent registerCompetitorEvent = new RaceLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), author, passId, c, boats.get(c)); raceLog.add(registerCompetitorEvent); competitorOnRaceLogRegistrationEvents.put(c, registerCompetitorEvent); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java index f8c4a107633..499e115a5be 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RegattaLogEventNotificationForwardingTest.java @@ -15,7 +15,9 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.RaceColumnListener; @@ -74,7 +76,7 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa receivedRegattaLogEvent[0] = event; } }); - final RegattaLogRegisterCompetitorEventImpl event = createRegattaLogEvent(); + final RegattaLogRegisterCompetitorAndBoatEvent event = createRegattaLogEvent(); leaderboard.getRegattaLog().add(event); assertSame(event, receivedRegattaLogEvent[0]); } @@ -96,14 +98,14 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa receivedRegattaLogEvent[0] = event; } }); - final RegattaLogRegisterCompetitorEventImpl event = createRegattaLogEvent(); + final RegattaLogRegisterCompetitorAndBoatEvent event = createRegattaLogEvent(); deserializedLeaderboard.getRegattaLog().add(event); assertSame(event, receivedRegattaLogEvent[0]); } - private RegattaLogRegisterCompetitorEventImpl createRegattaLogEvent() { - final RegattaLogRegisterCompetitorEventImpl event = new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), /* author */ null, - AbstractTracTracLiveTest.createCompetitorAndBoat("Someone").getCompetitor()); + private RegattaLogRegisterCompetitorAndBoatEvent createRegattaLogEvent() { + final RegattaLogRegisterCompetitorAndBoatEvent event = new RegattaLogRegisterCompetitorAndBoatEventImpl(MillisecondsTimePoint.now(), /* author */ null, + AbstractLeaderboardTest.createCompetitor("Someone"), AbstractLeaderboardTest.createBoat("Some boat")); return event; } @@ -129,7 +131,7 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa receivedRegattaLogEvent[0] = event; } }); - final RegattaLogRegisterCompetitorEventImpl event = createRegattaLogEvent(); + final RegattaLogRegisterCompetitorAndBoatEvent event = createRegattaLogEvent(); regatta.getRegattaLog().add(event); assertSame(event, receivedRegattaLogEvent[0]); } @@ -151,7 +153,7 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa receivedRegattaLogEvent[0] = event; } }); - final RegattaLogRegisterCompetitorEventImpl event = createRegattaLogEvent(); + final RegattaLogRegisterCompetitorAndBoatEvent event = createRegattaLogEvent(); deserializedRegatta.getRegattaLog().add(event); assertSame(event, receivedRegattaLogEvent[0]); } @@ -165,7 +167,7 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa LeaderboardDTO dto = leaderboard.getLeaderboardDTO(now.plus(10), Collections.emptySet(), /* addOverallDetails */ false, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE, /* fillTotalPointsUncorrected */ false); assertTrue(dto.competitors.isEmpty()); - final RegattaLogRegisterCompetitorEvent event = createRegattaLogEvent(); + final RegattaLogRegisterCompetitorAndBoatEvent event = createRegattaLogEvent(); regatta.getRegattaLog().add(event); LeaderboardDTO dto2 = leaderboard.computeDTO(now.plus(20), Collections.emptySet(), /* addOverallDetails */ false, /* waitForLatestAnalyses */ false, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE, /* fillTotalPointsUncorrected */ false); @@ -197,7 +199,7 @@ public class RegattaLogEventNotificationForwardingTest extends AbstractSerializa LeaderboardDTO dto = deserializedLeaderboard.getLeaderboardDTO(now.plus(10), Collections.emptySet(), /* addOverallDetails */ false, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE, /* fillTotalPointsUncorrected */ false); assertTrue(dto.competitors.isEmpty()); - final RegattaLogRegisterCompetitorEvent event = createRegattaLogEvent(); + final RegattaLogRegisterCompetitorAndBoatEvent event = createRegattaLogEvent(); deserializedLeaderboard.getRegatta().getRegattaLog().add(event); LeaderboardDTO dto2 = deserializedLeaderboard.computeDTO(now.plus(20), Collections.emptySet(), /* addOverallDetails */ false, /* waitForLatestAnalyses */ false, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE, /* fillTotalPointsUncorrected */ false); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java index 3719ae66517..0601e8b343f 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackBasedTest.java @@ -31,8 +31,8 @@ import com.sap.sailing.domain.base.Sideline; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorImpl; import com.sap.sailing.domain.base.impl.ControlPointWithTwoMarksImpl; import com.sap.sailing.domain.base.impl.CourseAreaImpl; import com.sap.sailing.domain.base.impl.CourseImpl; 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 9c5c12ebf3d..51ef72b3212 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 @@ -46,7 +46,6 @@ import com.sap.sailing.domain.common.tracking.GPSFix; import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.common.tracking.SensorFix; import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.leaderboard.impl.BoatProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException; import com.sap.sailing.domain.polars.PolarDataService; @@ -556,11 +555,6 @@ public class MockedTrackedRace implements DynamicTrackedRace { return null; } - @Override - public BoatProviderFromRaceColumnsAndRegattaLike getOrCreateBoatsProvider() { - return null; - } - @Override public Iterable getBoatsRegisteredInRegattaLog() { return null; 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 75dfcd195d1..4b6d60826f7 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 @@ -678,6 +678,9 @@ public class DomainFactoryImpl implements DomainFactory { if (isSeparateBoat && existingCompetitor.getShortName() != rc.getCompetitor().getShortName()) { // in case we find a boat info we only want to update the shortName field of the competitor (instead of using sailID) CompetitorStore competitorStore = baseDomainFactory.getCompetitorStore(); + + competitorStore.migrateCompetitorToHaveASeparateBoat(existingCompetitor, boatOfCompetitor); + boolean isOldCompetitorToUpdateDuringGetOrCreate = competitorStore.isCompetitorToUpdateDuringGetOrCreate(existingCompetitor); competitorStore.allowCompetitorResetToDefaults(existingCompetitor); existingCompetitor = competitorStore.getOrCreateCompetitor(existingCompetitor.getId(), existingCompetitor.getName(), diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java index 147bfd81995..fcac2fac31d 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java @@ -309,26 +309,15 @@ public interface RaceColumn extends Named { Iterable getAvailableMarks(Fleet fleet); /** - * Returns the competitor set registered in the race column's race log associated to the passed fleet. If competitor - * registration in RaceLog is {@link #disableCompetitorRegistrationOnRaceLog(Fleet) disabled} or in case of a + * Returns the competitor and their boats registered in the race column's race log associated to the passed fleet. If competitor + * registration in RaceLog is {@link #disableCompetitorAndBoatRegistrationOnRaceLog(Fleet) disabled} or in case of a * MetaLeaderboardColumn an empty set is returned. * - * @return competitors in RaceLog if registration {@link #enableCompetitorRegistrationOnRaceLog(Fleet) enabled} or - * empty set in case registration is {@link #disableCompetitorRegistrationOnRaceLog(Fleet) disabled} or this + * @return competitors and boats in RaceLog if registration {@link #enableCompetitorAndBoatRegistrationOnRaceLog(Fleet) enabled} or + * empty set in case registration is {@link #disableCompetitorAndBoatRegistrationOnRaceLog(Fleet) disabled} or this * column belongs to a {@link MetaLeaderboard} */ - Iterable getCompetitorsRegisteredInRacelog(Fleet fleet); - - /** - * Checks whether competitor registration on RaceLog is enabled. - * - * @return boolean if competitor registration on the RaceLog is enabled, false in case this column belongs to a - * {@link MetaLeaderboard} - * - * @see #enableCompetitorRegistrationOnRaceLog(Fleet) - * @see #disableCompetitorRegistrationOnRaceLog(Fleet) - */ - boolean isCompetitorRegistrationInRacelogEnabled(Fleet fleet); + Map getCompetitorsAndBoatsRegisteredInRacelog(Fleet fleet); /** * Checks whether competitor and boat registration on RaceLog is enabled. @@ -340,28 +329,7 @@ public interface RaceColumn extends Named { * @see #disableCompetitorAndBoatRegistrationOnRaceLog(Fleet) */ boolean isCompetitorAndBoatRegistrationInRacelogEnabled(Fleet fleet); - - /** - * Activates competitor registration on the race column's race log associated to the passed fleet. As a result, - * competitor registrations that were added to the race log before this was disabled by - * {@link #disableCompetitorRegistrationOnRaceLog(Fleet)} will again be honored.

- * - * Performs nothing in case this column belongs to a {@link MetaLeaderboard}. - */ - void enableCompetitorRegistrationOnRaceLog(Fleet fleet); - /** - * Disables competitor registration on the race column's race log associated to the passed fleet. Performs nothing - * in case this column belongs to a {@link MetaLeaderboard}. If there are already competitor registrations on the - * race log, those will not be removed from the log but they will be ignored, and the regatta log's competitor - * registrations will be used instead. Re-{@link #enableCompetitorRegistrationOnRaceLog(Fleet) enabling} competitor - * registrations in the race log will cause such existing registrations to be honored again. - *

- * - * Performs nothing in case this column belongs to a {@link MetaLeaderboard}. - */ - void disableCompetitorRegistrationOnRaceLog(Fleet fleet) throws NotRevokableException; - /** * Activates competitor and boat registration on the race column's race log associated to the passed fleet. As a result, * competitor and boat registrations that were added to the race log before this was disabled by @@ -384,22 +352,22 @@ public interface RaceColumn extends Named { void disableCompetitorAndBoatRegistrationOnRaceLog(Fleet fleet) throws NotRevokableException; /** - * Registers a competitor on the the race column's race log associated to the passed fleet. + * Registers a competitor and his boat on the the race column's race log associated to the passed fleet. * - * @throws CompetitorRegistrationOnRaceLogDisabledException - * thrown if competitor registration is {@link #disableCompetitorRegistrationOnRaceLog(Fleet) disabled} + * @throws CompetitorAndBoatRegistrationOnRaceLogDisabledException + * thrown if competitor registration is {@link #disableCompetitorAndBoatRegistrationOnRaceLog(Fleet) disabled} * on racelog as well as if RaceColumn belongs to a {@link MetaLeaderboard} */ - void registerCompetitor(Competitor competitor, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException; + void registerCompetitorAndBoat(Competitor competitor, Boat boat, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException; /** - * Registers competitors on the the race column's race log associated to the passed fleet. + * Registers competitors and their boats on the the race column's race log associated to the passed fleet. * - * @throws CompetitorRegistrationOnRaceLogDisabledException + * @throws CompetitorAndBoatRegistrationOnRaceLogDisabledException * thrown if competitor registration is disabled on racelog as well as if RaceColumn belongs to a * {@link MetaLeaderboard} */ - void registerCompetitors(Iterable competitor, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException; + void registerCompetitorsAndBoats(Map competitorsAndBoats, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException; /** * Deregisters a competitor on the the race column's race log associated to the passed fleet. @@ -418,7 +386,4 @@ public interface RaceColumn extends Named { * {@link MetaLeaderboard} */ void deregisterCompetitors(Iterable currentlyRegisteredCompetitors, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException; - - void registerCompetitorAndBoat(Competitor competitor, Boat boat, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException; - void registerCompetitorsAndBoats(Map competitorsAndBoats, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java index b4ebbf1e361..93d63e4c6d6 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java @@ -21,13 +21,9 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAnalyzer; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAndBoatsAnalyzer; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsAndBoatsFromRaceLogEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDefinedMarkAnalyzer; import com.sap.sailing.domain.abstractlog.shared.events.RegisterCompetitorEvent; @@ -264,19 +260,8 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem @Override public Iterable getAllCompetitors(final Fleet fleet) { - final Iterable result; - TrackedRace trackedRace = getTrackedRace(fleet); - if (trackedRace != null) { - result = trackedRace.getRace().getCompetitors(); - } else { - // if no tracked race is found, use competitors from race/regatta log depending on whether - // the mapping event is present or not; this assumes that if a tracked - // race exists, its competitors set takes precedence over what's in the race log. Usually, - // the tracked race will have the same competitors as those in the race log, or more because - // those from the regatta log are added to the tracked race as well. - Set viaRaceLog = new RegisteredCompetitorsAnalyzer(getRaceLog(fleet), getRegattaLog()).analyze(); - result = viaRaceLog; - } + Set result = new HashSet<>(); + Util.addAll(getAllCompetitorsAndTheirBoats(fleet).keySet(), result); return result; } @@ -306,26 +291,6 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem return result; } - @Override - public void registerCompetitor(Competitor competitor, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException { - registerCompetitors(Collections.singleton(competitor), fleet); - } - - @Override - public void registerCompetitors(Iterable competitors, Fleet fleet) - throws CompetitorRegistrationOnRaceLogDisabledException { - if (!isCompetitorRegistrationInRacelogEnabled(fleet)) { - throw new CompetitorRegistrationOnRaceLogDisabledException("Competitor registration not allowed for fleet "+fleet+" in column "+this); - } - TimePoint now = MillisecondsTimePoint.now(); - RaceLog raceLog = getRaceLog(fleet); - int passId = raceLog.getCurrentPassId(); - for (Competitor competitor : competitors) { - raceLog.add(new RaceLogRegisterCompetitorEventImpl(now, now, raceLogEventAuthorForRaceColumn, - UUID.randomUUID(), passId, competitor)); - } - } - @Override public void registerCompetitorAndBoat(Competitor competitor, Boat boat, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException { Map competitorsAndBoats = new HashMap<>(); @@ -337,7 +302,7 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem public void registerCompetitorsAndBoats(Map competitorsAndBoats, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException { if (!isCompetitorAndBoatRegistrationInRacelogEnabled(fleet)) { - throw new CompetitorAndBoatRegistrationOnRaceLogDisabledException("Competitor and boat registration not allowed for fleet "+fleet+" in column "+this); + throw new CompetitorAndBoatRegistrationOnRaceLogDisabledException("Competitor registration not allowed for fleet "+fleet+" in column "+this); } TimePoint now = MillisecondsTimePoint.now(); RaceLog raceLog = getRaceLog(fleet); @@ -357,7 +322,7 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem @Override public void deregisterCompetitors(Iterable competitors, Fleet fleet) throws CompetitorRegistrationOnRaceLogDisabledException { - if (!isCompetitorRegistrationInRacelogEnabled(fleet)) { + if (!isCompetitorAndBoatRegistrationInRacelogEnabled(fleet)) { throw new CompetitorRegistrationOnRaceLogDisabledException("Competitor registration not allowed for fleet "+fleet+" in column "+this); } HashSet competitorSet = new HashSet(); @@ -436,31 +401,6 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem return result; } - @Override - public void enableCompetitorRegistrationOnRaceLog(Fleet fleet) { - TimePoint now = MillisecondsTimePoint.now(); - RaceLog raceLog = getRaceLog(fleet); - int passId = raceLog.getCurrentPassId(); - raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(now, raceLogEventAuthorForRaceColumn, now, UUID.randomUUID(), passId)); - } - - @Override - public void disableCompetitorRegistrationOnRaceLog(Fleet fleet) throws NotRevokableException { - RaceLog raceLog = getRaceLog(fleet); - List events = new AllEventsOfTypeFinder<>(raceLog, true, RaceLogUseCompetitorsFromRaceLogEvent.class).analyze(); - for (RaceLogEvent event : events) { - raceLog.lockForRead(); - try { - event = raceLog.getEventById(event.getId()); - } finally { - raceLog.unlockAfterRead(); - } - if (event != null) { - raceLog.revokeEvent(raceLogEventAuthorForRaceColumn, event, "revoke triggered by GWT user action"); - } - } - } - @Override public void enableCompetitorAndBoatRegistrationOnRaceLog(Fleet fleet) { TimePoint now = MillisecondsTimePoint.now(); 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 e90c18cc3c4..12830773095 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 @@ -26,11 +26,11 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterBoatEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; -import com.sap.sailing.domain.abstractlog.shared.analyzing.BoatDeregistrator; -import com.sap.sailing.domain.abstractlog.shared.analyzing.BoatsInLogAnalyzer; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterEntryEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogBoatDeregistrator; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogBoatsInLogAnalyzer; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogEntriesInLogAnalyzer; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorDeregistrator; -import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; @@ -54,7 +54,6 @@ import com.sap.sailing.domain.common.RegattaNameAndRaceName; import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; import com.sap.sailing.domain.leaderboard.ScoringScheme; import com.sap.sailing.domain.leaderboard.impl.AbstractLeaderboardImpl; -import com.sap.sailing.domain.leaderboard.impl.BoatProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.racelog.RaceLogIdentifier; @@ -159,7 +158,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene private boolean useStartTimeInference; private transient CompetitorProviderFromRaceColumnsAndRegattaLike competitorsProvider; - private transient BoatProviderFromRaceColumnsAndRegattaLike boatsProvider; + private AbstractLogEventAuthor regattaLogEventAuthorForRegatta = new LogEventAuthorImpl( AbstractLeaderboardImpl.class.getName(), 0); @@ -425,14 +424,6 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene return competitorsProvider; } - @Override - public BoatProviderFromRaceColumnsAndRegattaLike getOrCreateBoatsProvider() { - if (boatsProvider == null) { - boatsProvider = new BoatProviderFromRaceColumnsAndRegattaLike(this); - } - return boatsProvider; - } - @Override public Iterable getAllCompetitors() { Set result = new HashSet(); @@ -865,7 +856,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene @Override public Iterable getCompetitorsRegisteredInRegattaLog() { RegattaLog regattaLog = getRegattaLog(); - CompetitorsInLogAnalyzer analyzer = new CompetitorsInLogAnalyzer<>( + RegattaLogEntriesInLogAnalyzer analyzer = new RegattaLogEntriesInLogAnalyzer<>( regattaLog); return analyzer.analyze(); } @@ -881,7 +872,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene TimePoint now = MillisecondsTimePoint.now(); for (Competitor competitor : competitors) { - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(now, now, regattaLogEventAuthorForRegatta, + regattaLog.add(new RegattaLogRegisterEntryEventImpl(now, now, regattaLogEventAuthorForRegatta, UUID.randomUUID(), competitor)); } } @@ -902,7 +893,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene @Override public Iterable getBoatsRegisteredInRegattaLog() { RegattaLog regattaLog = getRegattaLog(); - BoatsInLogAnalyzer analyzer = new BoatsInLogAnalyzer<>( + RegattaLogBoatsInLogAnalyzer analyzer = new RegattaLogBoatsInLogAnalyzer<>( regattaLog); return analyzer.analyze(); } @@ -931,7 +922,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene @Override public void deregisterBoats(Iterable boats) { RegattaLog regattaLog = getRegattaLike().getRegattaLog(); - BoatDeregistrator deregisterer = new BoatDeregistrator<>(regattaLog, boats, regattaLogEventAuthorForRegatta); + RegattaLogBoatDeregistrator deregisterer = new RegattaLogBoatDeregistrator<>(regattaLog, boats, regattaLogEventAuthorForRegatta); deregisterer.deregister(deregisterer.analyze()); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SimpleAbstractRaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SimpleAbstractRaceColumn.java index c4cd3aa8feb..05b6811c87e 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SimpleAbstractRaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SimpleAbstractRaceColumn.java @@ -1,11 +1,12 @@ package com.sap.sailing.domain.base.impl; import java.util.Collections; +import java.util.Map; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogRegisteredCompetitorsAnalyzer; -import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogUsesOwnCompetitorsAnalyzer; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogRegisteredCompetitorsAndBoatsAnalyzer; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogUsesOwnCompetitorsAndBoatsAnalyzer; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; @@ -122,23 +123,12 @@ public abstract class SimpleAbstractRaceColumn implements RaceColumn { } @Override - public Iterable getCompetitorsRegisteredInRacelog(final Fleet fleet) { + public Map getCompetitorsAndBoatsRegisteredInRacelog(final Fleet fleet) { RaceLog raceLog = getRaceLog(fleet); if (raceLog == null) { - return Collections.emptySet(); + return Collections.emptyMap(); } else { - RaceLogRegisteredCompetitorsAnalyzer analyzer = new RaceLogRegisteredCompetitorsAnalyzer(raceLog); - return analyzer.analyze(); - } - } - - @Override - public boolean isCompetitorRegistrationInRacelogEnabled(final Fleet fleet) { - RaceLog raceLog = getRaceLog(fleet); - if (raceLog == null) { - return false; - } else { - RaceLogUsesOwnCompetitorsAnalyzer analyzer = new RaceLogUsesOwnCompetitorsAnalyzer(raceLog); + RaceLogRegisteredCompetitorsAndBoatsAnalyzer analyzer = new RaceLogRegisteredCompetitorsAndBoatsAnalyzer(raceLog); return analyzer.analyze(); } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java index f67e9ae5fc4..29d5b5ee948 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumnsAndRegattaLike.java @@ -1,12 +1,9 @@ package com.sap.sailing.domain.leaderboard; -import com.sap.sailing.domain.leaderboard.impl.BoatProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.leaderboard.impl.CompetitorProviderFromRaceColumnsAndRegattaLike; import com.sap.sailing.domain.regattalike.HasRegattaLike; public interface HasRaceColumnsAndRegattaLike extends HasRegattaLike, HasRaceColumns { CompetitorProviderFromRaceColumnsAndRegattaLike getOrCreateCompetitorsProvider(); - - BoatProviderFromRaceColumnsAndRegattaLike getOrCreateBoatsProvider(); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java index 3be2500817a..f1492ae4fce 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java @@ -14,11 +14,11 @@ import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterBoatEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; -import com.sap.sailing.domain.abstractlog.shared.analyzing.BoatDeregistrator; -import com.sap.sailing.domain.abstractlog.shared.analyzing.BoatsInLogAnalyzer; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterEntryEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogBoatDeregistrator; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogBoatsInLogAnalyzer; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogEntriesInLogAnalyzer; import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorDeregistrator; -import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Fleet; @@ -53,12 +53,6 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI */ private transient CompetitorProviderFromRaceColumnsAndRegattaLike competitorsProvider; - /** - * Cache for the combined boats of this leaderboard; taken from the {@link TrackedRace#getRace() races of the - * tracked races} associated with this leaderboard. Updated when the set of tracked races changes. - */ - private transient BoatProviderFromRaceColumnsAndRegattaLike boatsProvider; - private final AbstractLogEventAuthor regattaLogEventAuthorForAbstractLeaderboard = new LogEventAuthorImpl( AbstractLeaderboardImpl.class.getName(), 0); @@ -126,14 +120,6 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI return competitorsProvider; } - @Override - public BoatProviderFromRaceColumnsAndRegattaLike getOrCreateBoatsProvider() { - if (boatsProvider == null) { - boatsProvider = new BoatProviderFromRaceColumnsAndRegattaLike(this); - } - return boatsProvider; - } - @Override public Competitor getCompetitorByIdAsString(String idAsString) { for (Competitor competitor : getAllCompetitors()) { @@ -221,7 +207,7 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI @Override public Iterable getCompetitorsRegisteredInRegattaLog() { RegattaLog regattaLog = getRegattaLike().getRegattaLog(); - CompetitorsInLogAnalyzer analyzer = new CompetitorsInLogAnalyzer<>( + RegattaLogEntriesInLogAnalyzer analyzer = new RegattaLogEntriesInLogAnalyzer<>( regattaLog); return analyzer.analyze(); } @@ -237,7 +223,7 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI TimePoint now = MillisecondsTimePoint.now(); for (Competitor competitor : competitors) { - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(now, now, regattaLogEventAuthorForAbstractLeaderboard, + regattaLog.add(new RegattaLogRegisterEntryEventImpl(now, now, regattaLogEventAuthorForAbstractLeaderboard, UUID.randomUUID(), competitor)); } } @@ -261,14 +247,14 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI */ @Override public Iterable getAllBoats() { - return getOrCreateBoatsProvider().getAllBoats(); + return getBoatsRegisteredInRegattaLog(); } @Override public Iterable getBoatsRegisteredInRegattaLog() { RegattaLog regattaLog = getRegattaLike().getRegattaLog(); - BoatsInLogAnalyzer analyzer = new BoatsInLogAnalyzer<>( + RegattaLogBoatsInLogAnalyzer analyzer = new RegattaLogBoatsInLogAnalyzer<>( regattaLog); return analyzer.analyze(); } @@ -297,7 +283,7 @@ public abstract class AbstractLeaderboardImpl extends AbstractSimpleLeaderboardI @Override public void deregisterBoats(Iterable boats) { RegattaLog regattaLog = getRegattaLike().getRegattaLog(); - BoatDeregistrator deregisterer = new BoatDeregistrator<>(regattaLog, boats, regattaLogEventAuthorForAbstractLeaderboard); + RegattaLogBoatDeregistrator deregisterer = new RegattaLogBoatDeregistrator<>(regattaLog, boats, regattaLogEventAuthorForAbstractLeaderboard); deregisterer.deregister(deregisterer.analyze()); } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/BoatProviderFromRaceColumnsAndRegattaLike.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/BoatProviderFromRaceColumnsAndRegattaLike.java deleted file mode 100644 index 8d3414e002c..00000000000 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/BoatProviderFromRaceColumnsAndRegattaLike.java +++ /dev/null @@ -1,230 +0,0 @@ -package com.sap.sailing.domain.leaderboard.impl; - -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; -import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; -import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; -import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; -import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterBoatEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; -import com.sap.sailing.domain.abstractlog.regatta.impl.BaseRegattaLogEventVisitor; -import com.sap.sailing.domain.abstractlog.shared.analyzing.BoatsInLogAnalyzer; -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.base.RaceColumnListener; -import com.sap.sailing.domain.base.impl.RaceColumnListenerWithDefaultAction; -import com.sap.sailing.domain.leaderboard.HasRaceColumnsAndRegattaLike; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; - -/** - * A caching provider of a boat set, based on the tracked races and {@link RaceLog}s of the {@link RaceColumn}s of - * a {@link HasRaceColumnsAndRegattaLike} and the {@link RegattaLog} of the same object. After an answer has been - * provided, it is cached. The cache is invalidated when one of the following events occurs: - *

    - *
  • a boat is registered with or unregistered from a race log of any of the race columns or the regatta log
  • - *
  • a race column is added or removed
  • - *
  • a tracked race is linked to or unlinked from any of the race columns
  • - *
  • the racelog is marked as providing it's own boats via the {@link RaceLogUseCompetitorsAndBoatsFromRaceLogEvent}
  • - *
  • the racelog is marked as no longer providing it's own boats by revoking an event of type {@link RaceLogUseCompetitorsAndBoatsFromRaceLogEvent}
  • - *
- * - * Note that objects of this type are not serializable. Classes using such objects shall not assign them to non-transient - * fields if they want to be serializable themselves. - * - * @author Frank Mittag - * - */ -public class BoatProviderFromRaceColumnsAndRegattaLike { - private static final Logger logger = Logger.getLogger(BoatProviderFromRaceColumnsAndRegattaLike.class - .getName()); - - private final HasRaceColumnsAndRegattaLike provider; - - private final RegattaLogEventVisitor regattaLogBoatsCacheInvalidationListener; - - private final RaceLogEventVisitor raceLogBoatsCacheInvalidationListener; - - private final RaceColumnListener raceColumnListener; - - private Iterable allBoatsCache; - - private final ConcurrentMap, Iterable> allBoatsCacheByRace; - - public BoatProviderFromRaceColumnsAndRegattaLike(HasRaceColumnsAndRegattaLike provider) { - super(); - this.provider = provider; - this.allBoatsCacheByRace = new ConcurrentHashMap<>(); - // A note regarding listener serializability: RaceLogListener and RegattaLogListener objects - // don't need to be serializable as the log listeners are a transient structure. The race column - // listeners, however, need to explicitly declare that they are transient. - // This enclosing object is intended not to be serialized and shall be re-constructed by - // its users after de-serialization. Therefore, the transient-ness of the log listeners works - // as intended, and the race column listener explicitly returns true from its isTransient() - // method. - regattaLogBoatsCacheInvalidationListener = new BaseRegattaLogEventVisitor() { - @Override - public void visit(RegattaLogRegisterBoatEvent event) { - invalidateAllBoatsCaches(); - } - - @Override - public void visit(RegattaLogRevokeEvent event) { - try { - if (RegattaLogRegisterBoatEvent.class.isAssignableFrom(Class.forName(event - .getRevokedEventType()))) { - invalidateAllBoatsCaches(); - } - } catch (ClassNotFoundException e) { - logger.log(Level.WARNING, - "Problem occurred trying to resolve revoked event class " + event.getRevokedEventType(), e); - } - } - }; - raceLogBoatsCacheInvalidationListener = new BaseRaceLogEventVisitor() { - - @Override - public void visit(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent event) { - invalidateAllBoatsCaches(); - } - - @Override - public void visit(RaceLogRevokeEvent event) { - try { - final Class revokedEventClass = Class.forName(event.getRevokedEventType()); - // - if (RaceLogRegisterCompetitorAndBoatEvent.class.isAssignableFrom(revokedEventClass) || - RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.class.isAssignableFrom(revokedEventClass)) { - invalidateAllBoatsCaches(); - } - } catch (ClassNotFoundException e) { - logger.log(Level.WARNING, - "Problem occurred trying to resolve revoked event class " + event.getRevokedEventType(), e); - } - } - }; - raceColumnListener = new RaceColumnListenerWithDefaultAction() { - private static final long serialVersionUID = -8678230058730043052L; - - @Override - public void defaultAction() { - } - - /** - * As the entire provider object is considered transient, its listeners are so, too. - */ - @Override - public boolean isTransient() { - return true; - } - - @Override - public void trackedRaceLinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) { - invalidateAllBoatsCaches(); - } - - @Override - public void trackedRaceUnlinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) { - invalidateAllBoatsCaches(); - } - - @Override - public void raceColumnAddedToContainer(RaceColumn raceColumn) { - invalidateAllBoatsCaches(); - } - - @Override - public void raceColumnRemovedFromContainer(RaceColumn raceColumn) { - invalidateAllBoatsCaches(); - } - }; - } - - public Iterable getAllBoats() { - if (allBoatsCache == null) { - final Set result = new HashSet<>(); - boolean hasRaceColumns = false; - for (RaceColumn rc : provider.getRaceColumns()) { - hasRaceColumns = true; - Util.addAll(rc.getAllCompetitorsAndTheirBoats().values(), result); - for (final Fleet fleet : rc.getFleets()) { - rc.getRaceLog(fleet).addListener(raceLogBoatsCacheInvalidationListener); - } - } - final RegattaLog regattaLog = provider.getRegattaLike().getRegattaLog(); - if (!hasRaceColumns) { - // If no race exists, the regatta log-provided boat registrations will not have - // been considered yet; add them: - final Set regattaLogProvidedBoats = new BoatsInLogAnalyzer<>(regattaLog).analyze(); - result.addAll(regattaLogProvidedBoats); - } - // else, don't add regatta log boats because they have been added in each column already. - // The boats are collected from the races. Those, however, will be the regatta log - // boats if the race does not define its own. - // Note: adding listeners is idempotent; at most one occurrence of this listener exists in the race/regatta log's - // listeners set - provider.addRaceColumnListener(raceColumnListener); - // consider {@link RegattaLog} competitor changes because the RaceColumns may have added the competitors from there - regattaLog.addListener(regattaLogBoatsCacheInvalidationListener); - allBoatsCache = result; - } - return allBoatsCache; - } - - /** - * Obtains boats from the regatta log and adds those from the tracked race for the raceColumn/fleet - * combination or the race log, if no tracked race is attached for this combination. - */ - public Iterable getAllBoats(final RaceColumn raceColumn, final Fleet fleet) { - Pair key = new Pair<>(raceColumn, fleet); - Iterable result = allBoatsCacheByRace.get(key); - if (result == null) { - final Set resultSet = new HashSet<>(); - // raceColumn already considers trackedRace, RaceLog and RegattaLog - Util.addAll(raceColumn.getAllCompetitorsAndTheirBoats(fleet).values(), resultSet); - // note: adding listeners is idempotent; at most one occurrence of this listener exists in the race/regatta log's - // listeners set - raceColumn.getRaceLog(fleet).addListener(raceLogBoatsCacheInvalidationListener); - provider.addRaceColumnListener(raceColumnListener); - // consider {@link RegattaLog} competitor changes because the RaceColumns may have added the competitors from there - provider.getRegattaLike().getRegattaLog().addListener(regattaLogBoatsCacheInvalidationListener); - result = resultSet; - allBoatsCacheByRace.put(key, result); - } - return result; - } - - private void invalidateAllBoatsCaches() { - allBoatsCache = null; - // note: adding listeners was idempotent; at most one occurrence of this listener exists in the regatta log's - // listeners set - provider.getRegattaLike().getRegattaLog().removeListener(regattaLogBoatsCacheInvalidationListener); - for (final RaceColumn rc : provider.getRaceColumns()) { - for (final Fleet fleet : rc.getFleets()) { - // note: adding listeners was idempotent; at most one occurrence of this listener exists in the race - // log's listeners set - rc.getRaceLog(fleet).removeListener(raceLogBoatsCacheInvalidationListener); - } - } - // note: adding listeners was idempotent; at most one occurrence of this listener exists in the race column - // listeners set - provider.removeRaceColumnListener(raceColumnListener); - allBoatsCacheByRace.clear(); // this is a little coarse-grained; but given the typical access patterns it - // should be good enough. - // The change frequency of boats lists on individual races is much lower than the access frequency to this - // structure. - } - -} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/CompetitorProviderFromRaceColumnsAndRegattaLike.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/CompetitorProviderFromRaceColumnsAndRegattaLike.java index a508ec868eb..9e7b0d27cfa 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/CompetitorProviderFromRaceColumnsAndRegattaLike.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/CompetitorProviderFromRaceColumnsAndRegattaLike.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.leaderboard.impl; import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -11,14 +12,18 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsAndBoatsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; import com.sap.sailing.domain.abstractlog.regatta.impl.BaseRegattaLogEventVisitor; -import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; +import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsAndBoatsInLogAnalyzer; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; @@ -37,8 +42,8 @@ import com.sap.sse.common.Util.Pair; *
  • a competitor is registered with or unregistered from a race log of any of the race columns or the regatta log
  • *
  • a race column is added or removed
  • *
  • a tracked race is linked to or unlinked from any of the race columns
  • - *
  • the racelog is marked as providing it's own competitors via the {@link RaceLogUseCompetitorsFromRaceLogEvent}
  • - *
  • the racelog is marked as no longer providing it's own competitors by revoking an event of type {@link RaceLogUseCompetitorsFromRaceLogEvent}
  • + *
  • the racelog is marked as providing it's own competitors via the {@link RaceLogUseCompetitorsAndBoatsFromRaceLogEvent}
  • + *
  • the racelog is marked as no longer providing it's own competitors by revoking an event of type {@link RaceLogUseCompetitorsAndBoatsFromRaceLogEvent}
  • * * * Note that objects of this type are not serializable. Classes using such objects shall not assign them to non-transient @@ -80,11 +85,15 @@ public class CompetitorProviderFromRaceColumnsAndRegattaLike { invalidateAllCompetitorsCaches(); } + public void visit(RegattaLogRegisterCompetitorAndBoatEvent event) { + invalidateAllCompetitorsCaches(); + } + @Override public void visit(RegattaLogRevokeEvent event) { try { - if (RegattaLogRegisterCompetitorEvent.class.isAssignableFrom(Class.forName(event - .getRevokedEventType()))) { + if (RegattaLogRegisterCompetitorEvent.class.isAssignableFrom(Class.forName(event.getRevokedEventType())) || + RegattaLogRegisterCompetitorAndBoatEvent.class.isAssignableFrom(Class.forName(event.getRevokedEventType()))) { invalidateAllCompetitorsCaches(); } } catch (ClassNotFoundException e) { @@ -99,18 +108,30 @@ public class CompetitorProviderFromRaceColumnsAndRegattaLike { invalidateAllCompetitorsCaches(); } + @Override + public void visit(RaceLogRegisterCompetitorAndBoatEvent event) { + invalidateAllCompetitorsCaches(); + } + @Override public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { invalidateAllCompetitorsCaches(); } + @Override + public void visit(RaceLogUseCompetitorsAndBoatsFromRaceLogEvent event) { + invalidateAllCompetitorsCaches(); + } + @Override public void visit(RaceLogRevokeEvent event) { try { final Class revokedEventClass = Class.forName(event.getRevokedEventType()); // if (RaceLogRegisterCompetitorEvent.class.isAssignableFrom(revokedEventClass) || - RaceLogUseCompetitorsFromRaceLogEvent.class.isAssignableFrom(revokedEventClass)) { + RaceLogUseCompetitorsFromRaceLogEvent.class.isAssignableFrom(revokedEventClass) || + RaceLogRegisterCompetitorAndBoatEvent.class.isAssignableFrom(revokedEventClass) || + RaceLogUseCompetitorsAndBoatsFromRaceLogEvent.class.isAssignableFrom(revokedEventClass)) { invalidateAllCompetitorsCaches(); } } catch (ClassNotFoundException e) { @@ -171,8 +192,8 @@ public class CompetitorProviderFromRaceColumnsAndRegattaLike { if (!hasRaceColumns) { // If no race exists, the regatta log-provided competitor registrations will not have // been considered yet; add them: - final Set regattaLogProvidedCompetitors = new CompetitorsInLogAnalyzer<>(regattaLog).analyze(); - result.addAll(regattaLogProvidedCompetitors); + final Map regattaLogProvidedCompetitors = new CompetitorsAndBoatsInLogAnalyzer<>(regattaLog).analyze(); + result.addAll(regattaLogProvidedCompetitors.keySet()); } // else, don't add regatta log competitors because they have been added in each column already. // The competitors are collected from the races. Those, however, will be the regatta log diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java index d55d72bd7e0..d0ddd1f8497 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java @@ -185,10 +185,6 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr return getFullLeaderboard().getOrCreateCompetitorsProvider(); } - public BoatProviderFromRaceColumnsAndRegattaLike getOrCreateBoatsProvider() { - return getFullLeaderboard().getOrCreateBoatsProvider(); - } - public Regatta getRegatta() { return getFullLeaderboard().getRegatta(); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java index 13356340de0..f9766d2bb45 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java @@ -238,6 +238,18 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R return result; } + @Override + public Map getAllCompetitorsAndTheirBoats() { + // TODO bug2822: What should we do here? Returning a boat makes only sense when the competitors keep their boats through all regattas + return Collections.emptyMap(); + } + + @Override + public Map getAllCompetitorsAndTheirBoats(Fleet fleet) { + // TODO bug2822: What should we do here? Returning a boat makes only sense when the competitors keep their boats through all regattas + return Collections.emptyMap(); + } + @Override public RegattaLog getRegattaLog() { return null; @@ -263,19 +275,6 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R return Collections.emptySet(); } - @Override - public void registerCompetitor(Competitor competitor, Fleet fleet) - throws CompetitorRegistrationOnRaceLogDisabledException { - throw new CompetitorRegistrationOnRaceLogDisabledException(); - } - - @Override - public void registerCompetitors(Iterable competitor, Fleet fleet) - throws CompetitorRegistrationOnRaceLogDisabledException { - throw new CompetitorRegistrationOnRaceLogDisabledException(); - } - - @Override public void registerCompetitorAndBoat(Competitor competitor, Boat boat, Fleet fleet) throws CompetitorAndBoatRegistrationOnRaceLogDisabledException { @@ -300,14 +299,6 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R throw new CompetitorRegistrationOnRaceLogDisabledException(); } - @Override - public void enableCompetitorRegistrationOnRaceLog(Fleet fleetByName) { - } - - @Override - public void disableCompetitorRegistrationOnRaceLog(Fleet fleetByName) { - } - @Override public void enableCompetitorAndBoatRegistrationOnRaceLog(Fleet fleetByName) { } @@ -316,18 +307,6 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R public void disableCompetitorAndBoatRegistrationOnRaceLog(Fleet fleetByName) { } - @Override - public Map getAllCompetitorsAndTheirBoats() { - // TODO bug2822: What should we do here? Returning a boat makes only sense when the competitors keep their boats through all regattas - return Collections.emptyMap(); - } - - @Override - public Map getAllCompetitorsAndTheirBoats(Fleet fleet) { - // TODO bug2822: What should we do here? Returning a boat makes only sense when the competitors keep their boats through all regattas - return Collections.emptyMap(); - } - /** * When the leaderboard name changes, notify this to this object's {@link RaceColumnListener}s as a * change of this race column's name, but only if no {@link Leaderboard#getDisplayName() display name} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java index 2547b155557..aaa83b444ec 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceLogListener.java @@ -296,7 +296,7 @@ public class DynamicTrackedRaceLogListener extends BaseRaceLogEventVisitor { @Override public void visit(RaceLogFixedMarkPassingEvent event) { if (markPassingUpdateListener != null) { - markPassingUpdateListener.addFixedPassing(event.getInvolvedBoats().get(0), event.getZeroBasedIndexOfPassedWaypoint(), + markPassingUpdateListener.addFixedPassing(event.getInvolvedCompetitors().get(0), event.getZeroBasedIndexOfPassedWaypoint(), event.getTimePointOfFixedPassing()); } } @@ -304,7 +304,7 @@ public class DynamicTrackedRaceLogListener extends BaseRaceLogEventVisitor { @Override public void visit(RaceLogSuppressedMarkPassingsEvent event) { if (markPassingUpdateListener != null) { - markPassingUpdateListener.addSuppressedPassing(event.getInvolvedBoats().get(0), + markPassingUpdateListener.addSuppressedPassing(event.getInvolvedCompetitors().get(0), event.getZeroBasedIndexOfFirstSuppressedWaypoint()); } } @@ -326,10 +326,10 @@ public class DynamicTrackedRaceLogListener extends BaseRaceLogEventVisitor { } if (revokedEvent instanceof RaceLogSuppressedMarkPassingsEvent) { - markPassingUpdateListener.removeSuppressedPassing(revokedEvent.getInvolvedBoats().get(0)); + markPassingUpdateListener.removeSuppressedPassing(revokedEvent.getInvolvedCompetitors().get(0)); } if (revokedEvent instanceof RaceLogFixedMarkPassingEvent) { - markPassingUpdateListener.removeFixedPassing(revokedEvent.getInvolvedBoats().get(0), + markPassingUpdateListener.removeFixedPassing(revokedEvent.getInvolvedCompetitors().get(0), ((RaceLogFixedMarkPassingEvent) revokedEvent).getZeroBasedIndexOfPassedWaypoint()); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index d7cbe012138..fc2b634b982 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -1086,6 +1086,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } /** + * TODO: bug 2822 Is this still required? * Converts the {@link Competitor} objects passed as {@code iterable} to {@link CompetitorDTO} objects. * The iteration order in the result matches that of the {@code iterable} passed. */ @@ -1098,6 +1099,19 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return result; } + /** + * Converts the {@link Competitor} objects passed as {@code iterable} to {@link CompetitorDTO} objects. + * The iteration order in the result matches that of the {@code iterable} passed. + */ + private List convertToCompetitorDTOs(Map competitorsAndBoats) { + List result = new ArrayList(); + for (Entry competitorAndBoatEntry : competitorsAndBoats.entrySet()) { + CompetitorDTO competitorDTO = baseDomainFactory.convertToCompetitorDTO(competitorAndBoatEntry.getKey(), competitorAndBoatEntry.getValue()); + result.add(competitorDTO); + } + return result; + } + private List convertToBoatDTOs(Iterable iterable) { List result = new ArrayList(); for (Boat b : iterable) { @@ -2524,7 +2538,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S final RaceLogTrackingState raceLogTrackingState = raceLog == null ? RaceLogTrackingState.NOT_A_RACELOG_TRACKED_RACE : new RaceLogTrackingStateAnalyzer(raceLog).analyze(); final boolean raceLogTrackerExists = raceLog == null ? false : getService().getRaceTrackerById(raceLog.getId()) != null; - final boolean competitorRegistrationsExist = raceLog == null ? false : !Util.isEmpty(raceColumn.getAllCompetitors(fleet)); + final boolean competitorRegistrationsExist = raceLog == null ? false : !Util.isEmpty(raceColumn.getAllCompetitorsAndTheirBoats(fleet).keySet()); final boolean courseExist = raceLog == null ? false : !Util.isEmpty(raceColumn.getCourseMarks(fleet)); final RaceLogTrackingInfoDTO raceLogTrackingInfo = new RaceLogTrackingInfoDTO(raceLogTrackerExists, competitorRegistrationsExist, courseExist, raceLogTrackingState); @@ -5466,7 +5480,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S private Competitor getCompetitor(CompetitorDTO dto) { return getService().getCompetitorStore().getExistingCompetitorByIdAsString(dto.getIdAsString()); } - + @Override public void setCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName, Set competitorDTOs) throws CompetitorRegistrationOnRaceLogDisabledException, NotFoundException { @@ -5477,13 +5491,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); Fleet fleet = getFleetByName(raceColumn, fleetName); - Iterable competitorsToRemove = raceColumn.getCompetitorsRegisteredInRacelog(fleet); + Map competitorsToRemove = raceColumn.getCompetitorsAndBoatsRegisteredInRacelog(fleet); HashSet competitorSetToRemove = new HashSet<>(); - Util.addAll(competitorsToRemove, competitorSetToRemove); + Util.addAll(competitorsToRemove.keySet(), competitorSetToRemove); filterDuplicates(competitorsToRegister, competitorSetToRemove); raceColumn.deregisterCompetitors(competitorSetToRemove, fleet); - raceColumn.registerCompetitors(competitorsToRegister, fleet); + + // TODO bug 2822: temporary commented out -> needs first cleanup of CompetitorDTO and BoatDTO passing + // raceColumn.registerCompetitors(competitorsToRegister, fleet); } @Override @@ -6053,7 +6069,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Competitor competitor = getCompetitor(competitorDTO); RaceLogFixedMarkPassingEvent oldFixedMarkPassingEvent = null; for (RaceLogEvent event : raceLog.getUnrevokedEvents()) { - if (event instanceof RaceLogFixedMarkPassingEventImpl && event.getInvolvedBoats().contains(competitor)) { + if (event instanceof RaceLogFixedMarkPassingEventImpl && event.getInvolvedCompetitors().contains(competitor)) { RaceLogFixedMarkPassingEvent fixedEvent = (RaceLogFixedMarkPassingEvent) event; if (Util.equalsWithNull(fixedEvent.getZeroBasedIndexOfPassedWaypoint(), indexOfWaypoint)) { oldFixedMarkPassingEvent = fixedEvent; @@ -6082,7 +6098,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Competitor competitor = getCompetitor(competitorDTO); NavigableSet unrevokedEvents = raceLog.getUnrevokedEvents(); for (RaceLogEvent event : unrevokedEvents) { - if (event instanceof RaceLogSuppressedMarkPassingsEvent && event.getInvolvedBoats().contains(competitor)) { + if (event instanceof RaceLogSuppressedMarkPassingsEvent && event.getInvolvedCompetitors().contains(competitor)) { oldSuppressedMarkPassingEvent = (RaceLogSuppressedMarkPassingsEvent) event; break; } @@ -6357,7 +6373,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S String fleetName) throws NotFoundException { RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); Fleet fleet = getFleetByName(raceColumn, fleetName); - return convertToCompetitorDTOs(raceColumn.getAllCompetitors(fleet)); + return convertToCompetitorDTOs(raceColumn.getAllCompetitorsAndTheirBoats(fleet).keySet()); } @Override @@ -6381,7 +6397,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S String fleetName) throws NotFoundException { RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); Fleet fleet = getFleetByName(raceColumn, fleetName); - return convertToCompetitorDTOs(raceColumn.getCompetitorsRegisteredInRacelog(fleet)); + return convertToCompetitorDTOs(raceColumn.getCompetitorsAndBoatsRegisteredInRacelog(fleet)); } @Override @@ -6389,7 +6405,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S String fleetName) throws NotFoundException { RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); Fleet fleet = getFleetByName(raceColumn, fleetName); - return raceColumn.isCompetitorRegistrationInRacelogEnabled(fleet); + return raceColumn.isCompetitorAndBoatRegistrationInRacelogEnabled(fleet); } private Fleet getFleetByName(RaceColumn raceColumn, String fleetName) throws NotFoundException{ @@ -6424,7 +6440,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public void disableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) throws NotRevokableException, NotFoundException { if (areCompetitorRegistrationsEnabledForRace(leaderboardName, raceColumnName, fleetName)){ RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); - raceColumn.disableCompetitorRegistrationOnRaceLog(getFleetByName(raceColumn, fleetName)); + raceColumn.disableCompetitorAndBoatRegistrationOnRaceLog(getFleetByName(raceColumn, fleetName)); } } @@ -6432,7 +6448,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public void enableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) throws IllegalArgumentException, NotFoundException { if (!areCompetitorRegistrationsEnabledForRace(leaderboardName, raceColumnName, fleetName)){ RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); - raceColumn.enableCompetitorRegistrationOnRaceLog(getFleetByName(raceColumn, fleetName)); + raceColumn.enableCompetitorAndBoatRegistrationOnRaceLog(getFleetByName(raceColumn, fleetName)); } } 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 c02a07b0145..0228ccd345d 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 @@ -2,10 +2,12 @@ package com.sap.sailing.mongodb.test; import static org.junit.Assert.assertEquals; +import java.io.Serializable; import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; import java.util.Collection; +import java.util.Collections; import java.util.UUID; import org.junit.Before; @@ -15,20 +17,51 @@ import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.MongoException; import com.mongodb.WriteConcern; +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.impl.BoatClassImpl; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; import com.sap.sailing.domain.base.impl.DomainFactoryImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicCompetitor; +import com.sap.sailing.domain.base.impl.NationalityImpl; +import com.sap.sailing.domain.base.impl.PersonImpl; +import com.sap.sailing.domain.base.impl.TeamImpl; import com.sap.sailing.domain.persistence.DomainObjectFactory; import com.sap.sailing.domain.persistence.MongoObjectFactory; import com.sap.sailing.domain.persistence.PersistenceFactory; import com.sap.sailing.domain.persistence.impl.CollectionNames; -import com.sap.sailing.domain.test.AbstractLeaderboardTest; +import com.sap.sse.common.Color; import com.sap.sse.common.Util; public class StoreAndLoadCompetitorsTest extends AbstractMongoDBTest { private DomainFactory domainFactory; + + private final static BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); + public static Competitor createCompetitor(String competitorName) { + return createCompetitor(competitorName, competitorName); + } + + public static Competitor createCompetitor(String competitorName, Serializable id) { + return new CompetitorImpl(id, competitorName, "KYC", Color.RED, null, null, new TeamImpl("STG", Collections.singleton( + new PersonImpl(competitorName, new NationalityImpl("GER"), + /* dateOfBirth */ null, "This is famous "+competitorName)), + new PersonImpl("Rigo van Maas", new NationalityImpl("NED"), + /* dateOfBirth */null, "This is Rigo, the coach")), + /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null); + } + + public static CompetitorWithBoat createCompetitorWithBoat(String competitorName) { + Competitor c = createCompetitor(competitorName); + DynamicBoat b = new BoatImpl("id12345", competitorName + "'s boat", boatClass, /* sailID */ null); + return new CompetitorWithBoatImpl(c, b); + } + public StoreAndLoadCompetitorsTest() throws UnknownHostException, MongoException { super(); } @@ -59,12 +92,12 @@ public class StoreAndLoadCompetitorsTest extends AbstractMongoDBTest { DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); dropCompetitorCollection(); - DynamicCompetitor c = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat(competitorName1).getCompetitor(); + DynamicCompetitor c = (DynamicCompetitor) createCompetitor(competitorName1); c.setShortName(competitorShortName1); c.setFlagImage(flagImageURI1); mongoObjectFactory.storeCompetitor(c); - Collection allCompetitors = domainObjectFactory.loadAllCompetitors(); + Collection allCompetitors = domainObjectFactory.loadAllCompetitors(); assertEquals(1, Util.size(allCompetitors)); DynamicCompetitor loadedCompetitor = (DynamicCompetitor) allCompetitors.iterator().next(); assertEquals(flagImageURI1, loadedCompetitor.getFlagImage()); @@ -90,7 +123,7 @@ public class StoreAndLoadCompetitorsTest extends AbstractMongoDBTest { DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); dropCompetitorCollection(); - DynamicCompetitor c = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Hasso", UUID.randomUUID()).getCompetitor(); + DynamicCompetitor c = (DynamicCompetitor) createCompetitor("Hasso", UUID.randomUUID()); mongoObjectFactory.storeCompetitor(c); assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors())); c.setName("Hasso Plattner"); @@ -104,7 +137,7 @@ public class StoreAndLoadCompetitorsTest extends AbstractMongoDBTest { DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); dropCompetitorCollection(); - DynamicCompetitor c = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Hasso").getCompetitor(); + DynamicCompetitor c = (DynamicCompetitor) createCompetitor("Hasso"); mongoObjectFactory.storeCompetitor(c); assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors())); @@ -118,7 +151,7 @@ public class StoreAndLoadCompetitorsTest extends AbstractMongoDBTest { DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); dropCompetitorCollection(); - DynamicCompetitor c = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Hasso", UUID.randomUUID()).getCompetitor(); + DynamicCompetitor c = (DynamicCompetitor) createCompetitor("Hasso", UUID.randomUUID()); mongoObjectFactory.storeCompetitor(c); assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors())); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java index b6c821f6d23..b9951252e07 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java @@ -34,12 +34,13 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorAndBoatEvent; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.common.racelog.Flags; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.persistence.PersistenceFactory; @@ -53,6 +54,7 @@ import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsTimePoint; public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { + private final static BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true); protected MongoObjectFactoryImpl mongoFactory = (MongoObjectFactoryImpl) PersistenceFactory.INSTANCE .getMongoObjectFactory(getMongoService(), new MockSmartphoneImeiServiceFinderFactory()); @@ -84,7 +86,7 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { assertEquals(expectedEvent.getCreatedAt(), actualEvent.getCreatedAt()); assertEquals(expectedEvent.getLogicalTimePoint(), actualEvent.getLogicalTimePoint()); assertEquals(expectedEvent.getId(), actualEvent.getId()); - assertEquals(expectedEvent.getInvolvedBoats().size(), Util.size(actualEvent.getInvolvedBoats())); + assertEquals(expectedEvent.getInvolvedCompetitors().size(), Util.size(actualEvent.getInvolvedCompetitors())); assertEquals(expectedEvent.getPassId(), actualEvent.getPassId()); } @@ -209,14 +211,15 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { } @Test - public void testStoreAndLoadRegisterCompetitorEvent() { - RaceLogRegisterCompetitorEvent expectedEvent = new RaceLogRegisterCompetitorEventImpl(expectedEventTime, + public void testStoreAndLoadRegisterCompetitorAndBoatEvent() { + RaceLogRegisterCompetitorAndBoatEvent expectedEvent = new RaceLogRegisterCompetitorAndBoatEventImpl(expectedEventTime, expectedEventTime, author, expectedId, expectedPassId, DomainFactory.INSTANCE.getOrCreateCompetitor( "comp", "comp", "c", null, null, null, null, - /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null)); + /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null, null), + DomainFactory.INSTANCE.getOrCreateBoat("boat", "b", boatClass, null, null)); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); - RaceLogRegisterCompetitorEvent actualEvent = loadEvent(dbObject); + RaceLogRegisterCompetitorAndBoatEvent actualEvent = loadEvent(dbObject); assertBaseFields(expectedEvent, actualEvent); assertEquals(expectedEvent.getCompetitor(), actualEvent.getCompetitor()); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java index 5ee3ee1f088..6186725cb1b 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java @@ -27,9 +27,9 @@ import java.util.logging.Logger; import org.junit.Test; import com.mongodb.MongoException; -import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterEntryEventImpl; +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.CompetitorAndBoat; @@ -418,18 +418,18 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest "123", regattaProxy.getSeries(), regattaProxy.isPersistent(), DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), /* defaultCourseAreaId */ null, /*buoyZoneRadiusInHullLengths*/ 2.0, /* useStartTimeInference */ true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new); - CompetitorAndBoat competitorAndBoat1 = AbstractLeaderboardTest.createCompetitorAndBoat("Humba1"); - CompetitorAndBoat competitorAndBoat2 = AbstractLeaderboardTest.createCompetitorAndBoat("Humba2"); - res.getCompetitorStore().addCompetitors(Arrays.asList(competitorAndBoat1.getCompetitor(), competitorAndBoat2.getCompetitor())); - regatta.getRegattaLog().add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Axel", 0), competitorAndBoat1.getCompetitor())); - regatta.getRegattaLog().add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Axel", 0), competitorAndBoat2.getCompetitor())); - assertTrue(Util.contains(regatta.getAllCompetitors(), competitorAndBoat1)); - assertTrue(Util.contains(regatta.getAllCompetitors(), competitorAndBoat2)); + Competitor competitor1 = AbstractLeaderboardTest.createCompetitor("Humba1"); + Competitor competitor2 = AbstractLeaderboardTest.createCompetitor("Humba2"); + res.getCompetitorStore().addCompetitors(Arrays.asList(competitor1, competitor2)); + regatta.getRegattaLog().add(new RegattaLogRegisterEntryEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Axel", 0), competitor1)); + regatta.getRegattaLog().add(new RegattaLogRegisterEntryEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Axel", 0), competitor2)); + assertTrue(Util.contains(regatta.getAllCompetitors(), competitor1)); + assertTrue(Util.contains(regatta.getAllCompetitors(), competitor2)); addRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regatta); RegattaLeaderboard fullLeaderboard = res.addRegattaLeaderboard(regatta.getRegattaIdentifier(), null, new int[] { 3, 5 }); // use the set-up and add a regatta leaderboard with eliminations that wraps the regatta leaderboard RegattaLeaderboardWithEliminations withEliminations = res.addRegattaLeaderboardWithEliminations("U16", /* leaderboardDisplayName */ "Display Name", fullLeaderboard); - res.apply(new UpdateEliminatedCompetitorsInLeaderboard(withEliminations.getName(), Collections.singleton(competitorAndBoat1.getCompetitor()))); + res.apply(new UpdateEliminatedCompetitorsInLeaderboard(withEliminations.getName(), Collections.singleton(competitor1))); DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); @@ -451,8 +451,8 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest assertTrue(loadedLeaderboardWithEliminations instanceof RegattaLeaderboardWithEliminations); assertEquals("Display Name", loadedLeaderboardWithEliminations.getDisplayName()); assertEquals(withEliminations.getAllCompetitors(), loadedLeaderboardWithEliminations.getAllCompetitors()); - assertTrue(((RegattaLeaderboardWithEliminations) loadedLeaderboardWithEliminations).isEliminated(competitorAndBoat1.getCompetitor())); - assertFalse(((RegattaLeaderboardWithEliminations) loadedLeaderboardWithEliminations).isEliminated(competitorAndBoat2.getCompetitor())); + assertTrue(((RegattaLeaderboardWithEliminations) loadedLeaderboardWithEliminations).isEliminated(competitor1)); + assertFalse(((RegattaLeaderboardWithEliminations) loadedLeaderboardWithEliminations).isEliminated(competitor2)); } @Test diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java index d9defb4a071..86416afe3bd 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java @@ -369,7 +369,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD RaceLogFinishPositioningConfirmedEvent loadedConfirmedEvent = (RaceLogFinishPositioningConfirmedEvent) loadedEvent; assertEquals(now, loadedConfirmedEvent.getLogicalTimePoint()); assertEquals(0, loadedConfirmedEvent.getPassId()); - assertEquals(0, loadedConfirmedEvent.getInvolvedBoats().size()); + assertEquals(0, loadedConfirmedEvent.getInvolvedCompetitors().size()); assertNull(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertNull(loadedConfirmedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertEquals(1, Util.size(loadedRaceLog.getFixes())); @@ -419,7 +419,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD assertEquals(event.getLogicalTimePoint(), loadedPositioningEvent.getLogicalTimePoint()); assertEquals(event.getPassId(), loadedPositioningEvent.getPassId()); assertEquals(event.getId(), loadedPositioningEvent.getId()); - assertEquals(event.getInvolvedBoats().size(), loadedPositioningEvent.getInvolvedBoats().size()); + assertEquals(event.getInvolvedCompetitors().size(), loadedPositioningEvent.getInvolvedCompetitors().size()); final CompetitorResults expectedCompetiorResults = event.getPositionedCompetitorsIDsNamesMaxPointsReasons(); final CompetitorResults loadedCompetitorResults = loadedPositioningEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons(); assertCompetitorResultsEqual(expectedCompetiorResults, loadedCompetitorResults); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java index d6b8207c8fe..73b0f572cf3 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java @@ -221,7 +221,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin assertEquals(event.getLogicalTimePoint(), loadedPositioningEvent.getLogicalTimePoint()); assertEquals(event.getPassId(), loadedPositioningEvent.getPassId()); assertEquals(event.getId(), loadedPositioningEvent.getId()); - assertEquals(event.getInvolvedBoats().size(), loadedPositioningEvent.getInvolvedBoats().size()); + assertEquals(event.getInvolvedCompetitors().size(), loadedPositioningEvent.getInvolvedCompetitors().size()); assertCompetitorResultsEqual(event.getPositionedCompetitorsIDsNamesMaxPointsReasons(), loadedPositioningEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertEquals(1, Util.size(loadedRaceLog.getFixes())); } finally { @@ -245,7 +245,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin assertEquals(event.getLogicalTimePoint(), loadedConfirmedEvent.getLogicalTimePoint()); assertEquals(event.getPassId(), loadedConfirmedEvent.getPassId()); assertEquals(event.getId(), loadedConfirmedEvent.getId()); - assertEquals(event.getInvolvedBoats().size(), loadedConfirmedEvent.getInvolvedBoats().size()); + assertEquals(event.getInvolvedCompetitors().size(), loadedConfirmedEvent.getInvolvedCompetitors().size()); assertCompetitorResultsEqual(event.getPositionedCompetitorsIDsNamesMaxPointsReasons(), loadedConfirmedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertEquals(1, Util.size(loadedRaceLog.getFixes())); } finally { @@ -267,7 +267,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin RaceLogFinishPositioningConfirmedEvent loadedConfirmedEvent = (RaceLogFinishPositioningConfirmedEvent) loadedEvent; assertEquals(now, loadedConfirmedEvent.getLogicalTimePoint()); assertEquals(0, loadedConfirmedEvent.getPassId()); - assertEquals(0, loadedConfirmedEvent.getInvolvedBoats().size()); + assertEquals(0, loadedConfirmedEvent.getInvolvedCompetitors().size()); assertNull(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertNull(loadedConfirmedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertEquals(1, Util.size(loadedRaceLog.getFixes())); diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java index 663514ab034..946693834b7 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java @@ -8,11 +8,9 @@ import java.util.logging.Logger; import org.json.simple.JSONObject; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorFactory; import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.CompetitorWithBoatFactory; import com.sap.sailing.domain.base.SharedDomainFactory; -import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.base.impl.DynamicTeam; import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; @@ -24,7 +22,7 @@ import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.RGBColor; public class CompetitorWithBoatJsonDeserializer implements JsonDeserializer { - protected final CompetitorFactory competitorFactory; + protected final CompetitorWithBoatFactory competitorWithBoatFactory; protected final JsonDeserializer teamJsonDeserializer; protected final JsonDeserializer boatJsonDeserializer; private static final Logger logger = Logger.getLogger(CompetitorWithBoatJsonDeserializer.class.getName()); @@ -34,12 +32,12 @@ public class CompetitorWithBoatJsonDeserializer implements JsonDeserializer teamJsonDeserializer, JsonDeserializer boatDeserializer) { - this.competitorFactory = competitorFactory; + public CompetitorWithBoatJsonDeserializer(CompetitorWithBoatFactory competitorWithBoatFactory, JsonDeserializer teamJsonDeserializer, JsonDeserializer boatDeserializer) { + this.competitorWithBoatFactory = competitorWithBoatFactory; this.teamJsonDeserializer = teamJsonDeserializer; this.boatJsonDeserializer = boatDeserializer; } @@ -92,12 +90,12 @@ public class CompetitorWithBoatJsonDeserializer implements JsonDeserializer public static RaceLogEventDeserializer create(SharedDomainFactory domainFactory, JsonDeserializer deviceDeserializer) { JsonDeserializer competitorDeserializer = CompetitorJsonDeserializer.create(domainFactory); + JsonDeserializer competitorWithBoatDeserializer = CompetitorWithBoatJsonDeserializer.create(domainFactory); return new RaceLogEventDeserializer( new RaceLogFlagEventDeserializer(competitorDeserializer), new RaceLogStartTimeEventDeserializer(competitorDeserializer), @@ -81,7 +84,7 @@ public class RaceLogEventDeserializer implements JsonDeserializer new RaceLogDenoteForTrackingEventDeserializer(competitorDeserializer, domainFactory), new RaceLogStartTrackingEventDeserializer(competitorDeserializer), new RaceLogRevokeEventDeserializer(competitorDeserializer), - new RaceLogRegisterCompetitorEventDeserializer(competitorDeserializer), + new RaceLogRegisterCompetitorEventDeserializer(competitorDeserializer, competitorWithBoatDeserializer), new RaceLogRegisterCompetitorAndBoatEventDeserializer(competitorDeserializer, BoatJsonDeserializer.create(domainFactory)), new RaceLogAdditionalScoringInformationEventDeserializer(competitorDeserializer), new RaceLogFixedMarkPassingEventDeserializer(competitorDeserializer), diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java index ba85cdddb62..b5e86ef052a 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorAndBoatEventDeserializer.java @@ -25,7 +25,7 @@ public class RaceLogRegisterCompetitorAndBoatEventDeserializer extends BaseRaceL @Override protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { - assert competitors.size() == 1 : "Expected exactly one competitor for RegisterCompetitorEvent"; + assert competitors.size() == 1 : "Expected exactly one competitor for RegisterCompetitorAndBoatEvent"; Boat boat = boatDeserializer.deserialize(object); return new RaceLogRegisterCompetitorAndBoatEventImpl(createdAt, timePoint, author, id, passId, competitors.get(0), boat); } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorEventDeserializer.java index 6272c1e5dbb..14a58db69ae 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorEventDeserializer.java @@ -9,19 +9,24 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sse.common.TimePoint; public class RaceLogRegisterCompetitorEventDeserializer extends BaseRaceLogEventDeserializer { + private final JsonDeserializer competitorWithBoatDeserializer; - public RaceLogRegisterCompetitorEventDeserializer(JsonDeserializer competitorDeserializer) { + public RaceLogRegisterCompetitorEventDeserializer(JsonDeserializer competitorDeserializer, JsonDeserializer competitorWithBoatDeserializer) { super(competitorDeserializer); + this.competitorWithBoatDeserializer = competitorWithBoatDeserializer; } @Override - protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) { + protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { assert competitors.size() == 1 : "Expected exactly one competitor for RegisterCompetitorEvent"; - return new RaceLogRegisterCompetitorEventImpl(createdAt, timePoint, author, id, passId, competitors.get(0)); + CompetitorWithBoat competitorWithBoat = competitorWithBoatDeserializer.deserialize(object); + return new RaceLogRegisterCompetitorEventImpl(createdAt, timePoint, author, id, passId, competitorWithBoat); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorAndBoatJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java similarity index 51% rename from java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorAndBoatJsonSerializer.java rename to java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java index 1494ca5d317..585480a153a 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorAndBoatJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java @@ -4,35 +4,35 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorAndBoat; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; import com.sap.sailing.server.gateway.serialization.JsonSerializer; -public class CompetitorAndBoatJsonSerializer implements JsonSerializer { +public class CompetitorWithBoatJsonSerializer implements JsonSerializer { private final JsonSerializer boatJsonSerializer; private final JsonSerializer competitorJsonSerializer; - public static CompetitorAndBoatJsonSerializer create() { - return new CompetitorAndBoatJsonSerializer(CompetitorJsonSerializer.create(), BoatJsonSerializer.create()); + public static CompetitorWithBoatJsonSerializer create() { + return new CompetitorWithBoatJsonSerializer(CompetitorJsonSerializer.create(), BoatJsonSerializer.create()); } - public CompetitorAndBoatJsonSerializer() { + public CompetitorWithBoatJsonSerializer() { this(null, null); } - public CompetitorAndBoatJsonSerializer(JsonSerializer competitorJsonSerializer, JsonSerializer boatJsonSerializer) { + public CompetitorWithBoatJsonSerializer(JsonSerializer competitorJsonSerializer, JsonSerializer boatJsonSerializer) { this.competitorJsonSerializer = competitorJsonSerializer; this.boatJsonSerializer = boatJsonSerializer; } @Override - public JSONObject serialize(CompetitorAndBoat competitorAndBoat) { - JSONObject serializedCompetitor = competitorJsonSerializer.serialize(competitorAndBoat.getCompetitor()); + public JSONObject serialize(CompetitorWithBoat competitor) { + JSONObject serializedCompetitor = competitorJsonSerializer.serialize(competitor); - serializedCompetitor.put(CompetitorJsonConstants.FIELD_SAIL_ID, competitorAndBoat.getBoat() == null ? "" : competitorAndBoat.getBoat().getSailID()); + serializedCompetitor.put(CompetitorJsonConstants.FIELD_SAIL_ID, competitor.getBoat() == null ? "" : competitor.getBoat().getSailID()); - if (boatJsonSerializer != null) { - serializedCompetitor.put(CompetitorJsonConstants.FIELD_BOAT, boatJsonSerializer.serialize(competitorAndBoat.getBoat())); + if (boatJsonSerializer != null && competitor.getBoat() != null) { + serializedCompetitor.put(CompetitorJsonConstants.FIELD_BOAT, boatJsonSerializer.serialize(competitor.getBoat())); } return serializedCompetitor; } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/BaseRaceLogEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/BaseRaceLogEventSerializer.java index 04b0f436ecb..6ac4fb4accd 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/BaseRaceLogEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/BaseRaceLogEventSerializer.java @@ -37,7 +37,7 @@ public abstract class BaseRaceLogEventSerializer implements JsonSerializer, Rac new RaceLogDenoteForTrackingEventSerializer(competitorSerializer), new RaceLogStartTrackingEventSerializer(competitorSerializer), new RaceLogRevokeEventSerializer(competitorSerializer), - new RaceLogRegisterBoatEventSerializer(competitorSerializer), new RaceLogRegisterCompetitorEventSerializer(competitorSerializer), new RaceLogRegisterCompetitorAndBoatEventSerializer(competitorSerializer), new RaceLogAdditionalScoringInformationSerializer(competitorSerializer), @@ -136,7 +135,6 @@ public class RaceLogEventSerializer implements JsonSerializer, Rac JsonSerializer denoteForTrackingSerializer, JsonSerializer createRaceSerializer, JsonSerializer revokeSerializer, - JsonSerializer registerBoatSerializer, JsonSerializer registerCompetitorSerializer, JsonSerializer registerCompetitorAndBoatSerializer, JsonSerializer additionalScoringInformationSerializer, diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterBoatEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterBoatEventSerializer.java deleted file mode 100644 index 7729f67d5ee..00000000000 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterBoatEventSerializer.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.sap.sailing.server.gateway.serialization.racelog.impl; - -import com.sap.sailing.domain.abstractlog.shared.events.RegisterBoatEvent; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.server.gateway.serialization.JsonSerializer; - -public class RaceLogRegisterBoatEventSerializer extends BaseRaceLogEventSerializer { - - public static final String VALUE_CLASS = RegisterBoatEvent.class.getSimpleName(); - - public RaceLogRegisterBoatEventSerializer( - JsonSerializer competitorSerializer) { - super(competitorSerializer); - } - - @Override - protected String getClassFieldValue() { - return VALUE_CLASS; - } -} diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/AbstractEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/AbstractEventSerializerTest.java index 1f9d5c80c20..9d3b6f72e38 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/AbstractEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/AbstractEventSerializerTest.java @@ -54,7 +54,7 @@ public abstract class AbstractEventSerializerTest emptyList()); + when(event.getInvolvedCompetitors()).thenReturn(Collections. emptyList()); when(event.getAuthor()).thenReturn(author); } diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java index fb3d55fd8da..9e365d43ca4 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java @@ -78,8 +78,8 @@ public class RaceLogCourseDesignChangedEventSerializerTest { assertEquals(event.getPassId(), deserializedEvent.getPassId()); assertEquals(event.getLogicalTimePoint(), deserializedEvent.getLogicalTimePoint()); assertEquals(event.getCourseDesignerMode(), deserializedEvent.getCourseDesignerMode()); - assertEquals(0, Util.size(event.getInvolvedBoats())); - assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); + assertEquals(0, Util.size(event.getInvolvedCompetitors())); + assertEquals(0, Util.size(deserializedEvent.getInvolvedCompetitors())); compareCourseData(event.getCourseDesign(), deserializedEvent.getCourseDesign()); } diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java index 007975c5c36..3e1653b065d 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java @@ -26,9 +26,12 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChanged import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorAndBoatEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.impl.BoatClassImpl; import com.sap.sailing.domain.common.CourseDesignerMode; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.common.racelog.RacingProcedureType; @@ -57,7 +60,6 @@ public class RaceLogEventSerializerTest { private JsonSerializer denoteForTrackingEventSerializer; private JsonSerializer startTrackingEventSerializer; private JsonSerializer revokeEventSerializer; - private JsonSerializer registerBoatEventSerializer; private JsonSerializer registerCompetitorEventSerializer; private JsonSerializer registerCompetitorAndBoatEventSerializer; private JsonSerializer additionalScoringInformationSerializer; @@ -90,7 +92,6 @@ public class RaceLogEventSerializerTest { denoteForTrackingEventSerializer = mock(JsonSerializer.class); startTrackingEventSerializer = mock(JsonSerializer.class); revokeEventSerializer = mock(JsonSerializer.class); - registerBoatEventSerializer = mock(JsonSerializer.class); registerCompetitorEventSerializer = mock(JsonSerializer.class); registerCompetitorAndBoatEventSerializer = mock(JsonSerializer.class); additionalScoringInformationSerializer = mock(JsonSerializer.class); @@ -108,7 +109,7 @@ public class RaceLogEventSerializerTest { pathfinderEventSerializer, gateLineOpeningTimeEventSerializer, startProcedureTypeChangedEventSerializer, protestStartTimeEventSerializer, windFixEventSerializer, denoteForTrackingEventSerializer, startTrackingEventSerializer, revokeEventSerializer, - registerBoatEventSerializer, registerCompetitorEventSerializer, registerCompetitorAndBoatEventSerializer, + registerCompetitorEventSerializer, registerCompetitorAndBoatEventSerializer, fixedMarkPassingEventSerializer, suppressedMarkPassingsSerializer, additionalScoringInformationSerializer, dependentStartTimeEventSerializer, startOfTrackingEventSerializer, useCompetitorsFromRaceLogEventSerializer, useBoatsFromRaceLogEventSerializer, @@ -245,13 +246,14 @@ public class RaceLogEventSerializerTest { } @Test - public void testRegisterCompetitorEventSerializer() { + public void testRegisterCompetitorAndBoatEventSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = new RaceLogRegisterCompetitorEventImpl(null, author, 0, - DomainFactory.INSTANCE - .getOrCreateCompetitor("comp", "comp", "c", null, null, null, null, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */ - null, null)); + Competitor c = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", "c", null, null, null, null, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */ + null, null); + Boat b = DomainFactory.INSTANCE.getOrCreateBoat("boat", "b", new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null, null); + + RaceLogEvent event = new RaceLogRegisterCompetitorAndBoatEventImpl(null, author, 0, c, b); serializer.serialize(event); - verify(registerCompetitorEventSerializer).serialize(event); + verify(registerCompetitorAndBoatEventSerializer).serialize(event); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java index 39ecdf518d3..49a50da94e1 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java @@ -76,8 +76,8 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { assertEquals(event.getId(), deserializedEvent.getId()); assertEquals(event.getPassId(), deserializedEvent.getPassId()); assertEquals(event.getLogicalTimePoint(), deserializedEvent.getLogicalTimePoint()); - assertEquals(0, Util.size(event.getInvolvedBoats())); - assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); + assertEquals(0, Util.size(event.getInvolvedCompetitors())); + assertEquals(0, Util.size(deserializedEvent.getInvolvedCompetitors())); assertNotNull(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertNotNull(deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertEquals(1, Util.size(event.getPositionedCompetitorsIDsNamesMaxPointsReasons())); @@ -95,8 +95,8 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { assertEquals(event.getId(), deserializedEvent.getId()); assertEquals(event.getPassId(), deserializedEvent.getPassId()); assertEquals(event.getLogicalTimePoint(), deserializedEvent.getLogicalTimePoint()); - assertEquals(0, Util.size(event.getInvolvedBoats())); - assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); + assertEquals(0, Util.size(event.getInvolvedCompetitors())); + assertEquals(0, Util.size(deserializedEvent.getInvolvedCompetitors())); assertNull(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertNotNull(deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertTrue(Util.isEmpty(deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons())); @@ -113,8 +113,8 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { assertEquals(event.getId(), deserializedEvent.getId()); assertEquals(event.getPassId(), deserializedEvent.getPassId()); assertEquals(event.getLogicalTimePoint(), deserializedEvent.getLogicalTimePoint()); - assertEquals(0, Util.size(event.getInvolvedBoats())); - assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); + assertEquals(0, Util.size(event.getInvolvedCompetitors())); + assertEquals(0, Util.size(deserializedEvent.getInvolvedCompetitors())); assertNotNull(event.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertNotNull(deserializedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons()); assertTrue(Util.isEmpty(event.getPositionedCompetitorsIDsNamesMaxPointsReasons())); diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java index 3ee5c285332..6b2e7f8abc4 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java @@ -67,8 +67,8 @@ public class RaceLogWindFixEventSerializerTest { assertEquals(event.getId(), deserializedEvent.getId()); assertEquals(event.getPassId(), deserializedEvent.getPassId()); assertEquals(event.getLogicalTimePoint(), deserializedEvent.getLogicalTimePoint()); - assertEquals(0, Util.size(event.getInvolvedBoats())); - assertEquals(0, Util.size(deserializedEvent.getInvolvedBoats())); + assertEquals(0, Util.size(event.getInvolvedCompetitors())); + assertEquals(0, Util.size(deserializedEvent.getInvolvedCompetitors())); compareWind(event.getWindFix(), deserializedEvent.getWindFix()); } diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java index 748c11f7608..c4bb45d2071 100755 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/ManeuversJsonSerializer.java @@ -7,7 +7,8 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.tracking.Maneuver; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sse.common.TimePoint; @@ -16,10 +17,10 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class ManeuversJsonSerializer extends AbstractTrackedRaceDataJsonSerializer { public final static String MANEUVERS = "maneuvers"; - private final CompetitorAndBoatJsonSerializer competitorSerializer; + private final CompetitorWithBoatJsonSerializer competitorSerializer; private final ManeuverJsonSerializer maneuverSerializer; - public ManeuversJsonSerializer(CompetitorAndBoatJsonSerializer competitorSerializer, ManeuverJsonSerializer maneuverSerializer) { + public ManeuversJsonSerializer(CompetitorWithBoatJsonSerializer competitorSerializer, ManeuverJsonSerializer maneuverSerializer) { super(); this.competitorSerializer = competitorSerializer; this.maneuverSerializer = maneuverSerializer; @@ -35,7 +36,7 @@ public class ManeuversJsonSerializer extends AbstractTrackedRaceDataJsonSerializ Boat boat = competitorAndBoatEntry.getValue(); final JSONObject forCompetitorJson = new JSONObject(); byCompetitorJson.add(forCompetitorJson); - forCompetitorJson.put(COMPETITOR, competitorSerializer.serialize(new CompetitorAndBoatImpl(competitor, boat))); + forCompetitorJson.put(COMPETITOR, competitorSerializer.serialize(new CompetitorWithBoatImpl(competitor, (DynamicBoat) boat))); final JSONArray maneuvers = new JSONArray(); forCompetitorJson.put(MANEUVERS, maneuvers); for (final Maneuver maneuver : getManeuversDuringRace(trackedRace, competitor)) { diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java index c9bf8b687eb..7e656c4fcc3 100755 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/MarkPassingsJsonSerializer.java @@ -11,7 +11,8 @@ import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedRace; @@ -26,7 +27,7 @@ public class MarkPassingsJsonSerializer extends AbstractTrackedRaceDataJsonSeria public JSONObject serialize(TrackedRace trackedRace) { final Course course = trackedRace.getRace().getCourse(); JSONObject result = new JSONObject(); - CompetitorAndBoatJsonSerializer competitorWithBoatSerializer = CompetitorAndBoatJsonSerializer.create(); + CompetitorWithBoatJsonSerializer competitorWithBoatSerializer = CompetitorWithBoatJsonSerializer.create(); CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create(); JSONArray byCompetitorJson = new JSONArray(); result.put(BYCOMPETITOR, byCompetitorJson); @@ -35,7 +36,7 @@ public class MarkPassingsJsonSerializer extends AbstractTrackedRaceDataJsonSeria Boat boat = competitorAndBoatEntry.getValue(); JSONObject forCompetitorJson = new JSONObject(); byCompetitorJson.add(forCompetitorJson); - forCompetitorJson.put(COMPETITOR, competitorWithBoatSerializer.serialize(new CompetitorAndBoatImpl(competitor, boat))); + forCompetitorJson.put(COMPETITOR, competitorWithBoatSerializer.serialize(new CompetitorWithBoatImpl(competitor, (DynamicBoat) boat))); final NavigableSet markPassingsForCompetitor = trackedRace.getMarkPassings(competitor); JSONArray markPassingsForCompetitorJson = new JSONArray(); forCompetitorJson.put(MARKPASSINGS, markPassingsForCompetitorJson); diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RaceEntriesJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RaceEntriesJsonSerializer.java index 859140b0d90..231fbec82a3 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RaceEntriesJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RaceEntriesJsonSerializer.java @@ -7,33 +7,34 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorAndBoat; +import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.server.gateway.serialization.JsonSerializer; public class RaceEntriesJsonSerializer implements JsonSerializer { public static final String FIELD_NAME = "name"; public static final String FIELD_COMPETITORS = "competitors"; - private final JsonSerializer competitorAndBoatSerializer; + private final JsonSerializer competitorWithBoatSerializer; public RaceEntriesJsonSerializer() { this(null); } - public RaceEntriesJsonSerializer(JsonSerializer competitorAndBoatSerializer) { - this.competitorAndBoatSerializer = competitorAndBoatSerializer; + public RaceEntriesJsonSerializer(JsonSerializer competitorWithBoatSerializer) { + this.competitorWithBoatSerializer = competitorWithBoatSerializer; } public JSONObject serialize(RaceDefinition race) { JSONObject result = new JSONObject(); result.put(FIELD_NAME, race.getName()); - if(competitorAndBoatSerializer != null) { + if(competitorWithBoatSerializer != null) { JSONArray competitorsJson = new JSONArray(); for (Entry competitorAndBoatEntry: race.getCompetitorsAndTheirBoats().entrySet()) { - competitorsJson.add(competitorAndBoatSerializer.serialize(new CompetitorAndBoatImpl(competitorAndBoatEntry.getKey(), - competitorAndBoatEntry.getValue()))); + competitorsJson.add(competitorWithBoatSerializer.serialize(new CompetitorWithBoatImpl(competitorAndBoatEntry.getKey(), + (DynamicBoat) competitorAndBoatEntry.getValue()))); } result.put(FIELD_COMPETITORS, competitorsJson); } diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java index 510a5a14bcc..1079f29b343 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/LeaderboardsResourceCheckinAndOutTest.java @@ -9,7 +9,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.UUID; import javax.ws.rs.core.Response; @@ -20,7 +19,8 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceCompetitorMappingFinder; -import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsInLogAnalyzer; +import com.sap.sailing.domain.abstractlog.shared.analyzing.CompetitorsAndBoatsInLogAnalyzer; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.impl.BoatClassImpl; @@ -75,7 +75,7 @@ public class LeaderboardsResourceCheckinAndOutTest extends AbstractJaxRsApiTest Response response = resource.postCheckin(json.toString(), leaderboard.getName()); assertThat("checkin returns OK", response.getStatus(), equalTo(Response.Status.OK.getStatusCode())); - Set registeredCompetitors = new CompetitorsInLogAnalyzer<>(log).analyze(); + Map registeredCompetitors = new CompetitorsAndBoatsInLogAnalyzer<>(log).analyze(); Map>> mappings = new RegattaLogDeviceCompetitorMappingFinder( log).analyze(); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java index aef98773eb3..df847b8830e 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java @@ -36,7 +36,8 @@ import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.impl.CompetitorAndBoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.Position; @@ -67,7 +68,7 @@ import com.sap.sailing.server.gateway.serialization.coursedata.impl.WaypointJson import com.sap.sailing.server.gateway.serialization.impl.AbstractTrackedRaceDataJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.ColorJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.CompetitorAndBoatJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorWithBoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.DefaultWindTrackJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.DistanceJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.FleetJsonSerializer; @@ -211,7 +212,7 @@ public class RegattasResource extends AbstractSailingServerResource { if (race == null) { response = getBadRaceErrorResponse(regattaName, raceName); } else { - CompetitorAndBoatJsonSerializer competitorJsonSerializer = CompetitorAndBoatJsonSerializer.create(); + CompetitorWithBoatJsonSerializer competitorJsonSerializer = CompetitorWithBoatJsonSerializer.create(); JsonSerializer raceEntriesSerializer = new RaceEntriesJsonSerializer(competitorJsonSerializer); JSONObject serializedRaceEntries = raceEntriesSerializer.serialize(race); @@ -861,7 +862,7 @@ public class RegattasResource extends AbstractSailingServerResource { .build(); } else { TrackedRace trackedRace = findTrackedRace(regattaName, raceName); - ManeuversJsonSerializer serializer = new ManeuversJsonSerializer(new CompetitorAndBoatJsonSerializer(), + ManeuversJsonSerializer serializer = new ManeuversJsonSerializer(new CompetitorWithBoatJsonSerializer(), new ManeuverJsonSerializer(new GPSFixJsonSerializer(), new DistanceJsonSerializer())); JSONObject jsonMarkPassings = serializer.serialize(trackedRace); String json = jsonMarkPassings.toJSONString(); @@ -930,11 +931,11 @@ public class RegattasResource extends AbstractSailingServerResource { return result; }); } - CompetitorAndBoatJsonSerializer serializer = new CompetitorAndBoatJsonSerializer(); + CompetitorWithBoatJsonSerializer serializer = new CompetitorWithBoatJsonSerializer(); JSONArray result = new JSONArray(); for (final Competitor c : competitors) { Boat boat = trackedRace.getBoatOfCompetitor(c); - JSONObject jsonCompetitor = serializer.serialize(new CompetitorAndBoatImpl(c, boat)); + JSONObject jsonCompetitor = serializer.serialize(new CompetitorWithBoatImpl(c, (DynamicBoat) boat)); result.add(jsonCompetitor); } String json = result.toJSONString(); diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java index 395f020fb01..c489a1a89bf 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java @@ -181,7 +181,7 @@ public class RaceLogReplicationTest extends AbstractLogReplicationTestnull); - DynamicCompetitor template = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor(); + DynamicCompetitor template = (DynamicCompetitor) AbstractLeaderboardTest.createCompetitor("Test Competitor"); Competitor competitor = persistentStore1.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null); @@ -72,7 +75,7 @@ public class CompetitorStoreTest { assertEquals(1.234, competitor2.getTimeOnTimeFactor(), 0.0000001); assertEquals(730, competitor2.getTimeOnDistanceAllowancePerNauticalMile().asSeconds(), 0.0000001); - DynamicTeam differentTeam = (DynamicTeam) AbstractLeaderboardTest.createCompetitorAndBoat("Test Competitor").getCompetitor().getTeam(); + DynamicTeam differentTeam = (DynamicTeam) AbstractLeaderboardTest.createCompetitor("Test Competitor").getTeam(); differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana Competitor competitor3 = persistentStore2.getOrCreateCompetitor(template.getId(), template.getName(), template.getShortName(), template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ @@ -89,7 +92,43 @@ public class CompetitorStoreTest { assertSame(competitor2, competitor4); // expecting an in-place update assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); } - + + @Test + public void testPersistentCompetitorWithBoatStore() { + CompetitorStore persistentStore1 = new PersistentCompetitorStore( + PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */true, null, /* raceLogResolver */ (srlid)->null); + DynamicCompetitorWithBoat template = (DynamicCompetitorWithBoat) AbstractLeaderboardTest.createCompetitorWithBoat("Test Competitor"); + CompetitorWithBoat competitor = persistentStore1.getOrCreateCompetitorWithBoat(template.getId(), template.getName(), template.getShortName(), + template.getColor(), template.getEmail(), template.getFlagImage(), template.getTeam(), + /* timeOnTimeFactor */ 1.234, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ Duration.ONE_SECOND.times(730), null, template.getBoat()); + + CompetitorStore persistentStore2 = new PersistentCompetitorStore( + PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), /* clearStore */false, null, /* raceLogResolver */ (srlid)->null); + CompetitorWithBoat competitor2 = persistentStore2.getExistingCompetitorWithBoatById(template.getId()); + assertNotSame(competitor2, template); // the new store loads new instances from the database + assertEquals(template.getId(), competitor2.getId()); + assertEquals(template.getTeam().getNationality(), competitor2.getTeam().getNationality()); + assertEquals(1.234, competitor2.getTimeOnTimeFactor(), 0.0000001); + assertEquals(730, competitor2.getTimeOnDistanceAllowancePerNauticalMile().asSeconds(), 0.0000001); + + DynamicTeam differentTeam = (DynamicTeam) AbstractLeaderboardTest.createCompetitorWithBoat("Test Competitor").getTeam(); + differentTeam.setNationality(DomainFactory.INSTANCE.getOrCreateNationality("GHA")); // Ghana + CompetitorWithBoat competitor3 = persistentStore2.getOrCreateCompetitorWithBoat(template.getId(), template.getName(), template.getShortName(), + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null, template.getBoat()); + assertSame(competitor2, competitor3); // use existing competitor despite the different team + assertNotSame(differentTeam, competitor2.getTeam()); // team expected to remain unchanged + assertEquals(competitor.getTeam().getNationality(), competitor3.getTeam().getNationality()); // no updatability requested; nationality + // expected to remain unchanged + // now mark the competitor as to update from defaults + persistentStore2.allowCompetitorWithBoatResetToDefaults(competitor2); + CompetitorWithBoat competitor4 = persistentStore2.getOrCreateCompetitorWithBoat(template.getId(), template.getName(), template.getShortName(), + template.getColor(), template.getEmail(), template.getFlagImage(), differentTeam, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */null, null, template.getBoat()); + assertSame(competitor2, competitor4); // expecting an in-place update + assertEquals(differentTeam.getNationality(), competitor4.getTeam().getNationality()); + } + @Test public void testPersistentBoatStore() { CompetitorStore persistentStore1 = new PersistentCompetitorStore( diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java index 70bbfd900bc..5d805358e28 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java @@ -52,9 +52,10 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterEntryEvent; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorBravoMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterEntryEventImpl; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; @@ -292,7 +293,7 @@ public class MasterDataImportTest { // Set RegattaLog event TimePoint regattaLogTimepoint = new MillisecondsTimePoint(84392048L); - RegattaLogRegisterCompetitorEvent registerEvent = new RegattaLogRegisterCompetitorEventImpl( + RegattaLogRegisterEntryEvent registerEvent = new RegattaLogRegisterEntryEventImpl( regattaLogTimepoint, regattaLogTimepoint, author, UUID.randomUUID(), competitor); regatta.getRegattaLog().add(registerEvent); 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 3bee1d8a5e3..730de4a79e5 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 @@ -51,14 +51,19 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl this.loadFrom = PersistenceFactory.INSTANCE.getDomainObjectFactory(MongoDBService.INSTANCE, baseDomainFactory, serviceFinderFactory); this.storeTo = storeTo; if (clearCompetitorsAndBaots) { + storeTo.removeAllCompetitorsWithBoat(); storeTo.removeAllCompetitors(); storeTo.removeAllBoats(); } else { // TODO bug2822: How to migrate the competitors with contained boats to competitors with separate boat - Collection allCompetitors = loadFrom.loadAllCompetitors(); - for (CompetitorWithBoat competitor : allCompetitors) { + Collection allCompetitors = loadFrom.loadAllCompetitors(); + for (Competitor competitor : allCompetitors) { addCompetitorToTransientStore(competitor.getId(), competitor); } + Collection allCompetitorsWithBoat = loadFrom.loadAllCompetitorsWithBoat(); + for (CompetitorWithBoat competitor : allCompetitorsWithBoat) { + addCompetitorWithBoatToTransientStore(competitor.getId(), competitor); + } Collection allBoats = loadFrom.loadAllBoats(); for (Boat boat: allBoats) { addBoatToTransientStore(boat.getId(), boat); @@ -86,8 +91,15 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl ois.defaultReadObject(); storeTo = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(); } - - private void addCompetitorToTransientStore(Serializable id, CompetitorWithBoat competitor) { + + @Override + public void migrateCompetitorToHaveASeparateBoat(Competitor existingCompetitor, Boat separateBoat) { + storeTo.storeCompetitor(existingCompetitor); + storeTo.storeBoat(separateBoat); + super.addNewBoat(separateBoat.getId(), separateBoat); + } + + private void addCompetitorToTransientStore(Serializable id, Competitor competitor) { super.addNewCompetitor(id, competitor); } @@ -124,6 +136,46 @@ public class PersistentCompetitorStore extends TransientCompetitorStoreImpl impl storeTo.storeCompetitors(competitors); super.addCompetitors(competitors); } + + ///////////// + private void addCompetitorWithBoatToTransientStore(Serializable id, CompetitorWithBoat competitor) { + super.addNewCompetitorWithBoat(id, competitor); + } + + @Override + protected void addNewCompetitorWithBoat(Serializable id, CompetitorWithBoat competitor) { + storeTo.storeCompetitorWithBoat(competitor); + super.addNewCompetitorWithBoat(id, competitor); + } + + @Override + public void clearCompetitorsWithBoat() { + storeTo.removeAllCompetitorsWithBoat(); + super.clearCompetitorsWithBoat(); + } + + @Override + public void removeCompetitorWithBoat(CompetitorWithBoat competitor) { + storeTo.removeCompetitorWithBoat(competitor); + super.removeCompetitorWithBoat(competitor); + } + + @Override + public CompetitorWithBoat updateCompetitorWithBoat(String idAsString, String newName, String newShortName, Color newRgbDisplayColor, String newEmail, + Nationality newNationality, URI newTeamImageUri, URI newFlagImageUri, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile, + String searchTag) { + CompetitorWithBoat result = super.updateCompetitorWithBoat(idAsString, newName, newShortName, newRgbDisplayColor, newEmail, newNationality, + newTeamImageUri, newFlagImageUri, timeOnTimeFactor, timeOnDistanceAllowancePerNauticalMile, searchTag); + storeTo.storeCompetitorWithBoat(result); + return result; + } + + @Override + public void addCompetitorsWithBoat(Iterable competitors) { + storeTo.storeCompetitorsWithBoat(competitors); + super.addCompetitorsWithBoat(competitors); + } + private void addBoatToTransientStore(Serializable id, Boat boat) { super.addNewBoat(id, boat); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java index 2acd7a366ef..7b7e4b43771 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java @@ -471,18 +471,18 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes /** * Constructs a {@link DomainFactory base domain factory} that uses this object's {@link #competitorStore competitor - * store} for competitor management. This base domain factory is then also used for the construction of the - * {@link DomainObjectFactory}. This constructor variant initially clears the persistent competitor collection, - * hence removes all previously persistent competitors. This is the default for testing and for backward - * compatibility with prior releases that did not support a persistent competitor collection. + * store} for competitor and boat management. This base domain factory is then also used for the construction of the + * {@link DomainObjectFactory}. This constructor variant initially clears the persistent competitor and boat collections, + * hence removes all previously persistent competitors and boats. This is the default for testing and for backward + * compatibility with prior releases that did not support a persistent competitor and boat collection. */ public RacingEventServiceImpl() { - this(/* clearPersistentCompetitorStore */ true, /* serviceFinderFactory */ null, /* restoreTrackedRaces */ false); + this(/* clearPersistentCompetitorAndBoatStore */ true, /* serviceFinderFactory */ null, /* restoreTrackedRaces */ false); } public RacingEventServiceImpl(WindStore windStore, SensorFixStore sensorFixStore, TypeBasedServiceFinderFactory serviceFinderFactory) { - this(/* clearPersistentCompetitorStore */ true, windStore, sensorFixStore, serviceFinderFactory, + this(/* clearPersistentCompetitorAndBoatStore */ true, windStore, sensorFixStore, serviceFinderFactory, /* sailingNotificationService */ null, /* restoreTrackedRaces */ false); } @@ -490,8 +490,8 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes this.bundleContext = bundleContext; } - public RacingEventServiceImpl(boolean clearPersistentCompetitorStore, final TypeBasedServiceFinderFactory serviceFinderFactory, boolean restoreTrackedRaces) { - this(clearPersistentCompetitorStore, serviceFinderFactory, null, /* sailingNotificationService */ null, restoreTrackedRaces); + public RacingEventServiceImpl(boolean clearPersistentCompetitorAndBoatStore, final TypeBasedServiceFinderFactory serviceFinderFactory, boolean restoreTrackedRaces) { + this(clearPersistentCompetitorAndBoatStore, serviceFinderFactory, null, /* sailingNotificationService */ null, restoreTrackedRaces); } /** @@ -506,14 +506,14 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes * a notification service to call upon events worth notifying users about, or {@code null} if no * notification service is available, e.g., in test set-ups */ - public RacingEventServiceImpl(boolean clearPersistentCompetitorStore, final TypeBasedServiceFinderFactory serviceFinderFactory, + public RacingEventServiceImpl(boolean clearPersistentCompetitorAndBoatStore, final TypeBasedServiceFinderFactory serviceFinderFactory, TrackedRegattaListener trackedRegattaListener, SailingNotificationService sailingNotificationService, boolean restoreTrackedRaces) { this((final RaceLogResolver raceLogResolver)-> { return new ConstructorParameters() { private final MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory); private final PersistentCompetitorStore competitorStore = new PersistentCompetitorStore( PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory), - clearPersistentCompetitorStore, serviceFinderFactory, raceLogResolver); + clearPersistentCompetitorAndBoatStore, serviceFinderFactory, raceLogResolver); @Override public DomainObjectFactory getDomainObjectFactory() { return competitorStore.getDomainObjectFactory(); } @Override public MongoObjectFactory getMongoObjectFactory() { return mongoObjectFactory; }