From 06447318e58856c25bf8592e6aa3cef73d074ceb Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Mon, 9 Apr 2018 16:39:17 +0200 Subject: [PATCH 1/5] bug4500: consolidated the two Competitor Json (De-)Serializers into one Change-Id: I517a2649b6175f11f5e1c7b35fdc439f1982dca4 --- .../impl/CompetitorJsonDeserializer.java | 40 ++++--- .../CompetitorWithBoatJsonDeserializer.java | 103 ------------------ ...itorWithContainedBoatJsonDeserializer.java | 3 - .../impl/RaceLogEventDeserializer.java | 5 +- ...ogRegisterCompetitorEventDeserializer.java | 29 ++--- .../impl/CompetitorJsonSerializer.java | 25 ++++- .../CompetitorWithBoatJsonSerializer.java | 33 ------ .../CompetitorWithBoatRefJsonSerializer.java | 3 +- .../racelog/impl/RaceLogEventSerializer.java | 3 +- ...eLogRegisterCompetitorEventSerializer.java | 29 ++--- .../test/CompetitorJsonSerializerTest.java | 58 +++++++++- ...sitioningConfirmedEventSerializerTest.java | 15 +-- .../RaceLogWindFixEventSerializerTest.java | 7 +- .../impl/ManeuversJsonSerializer.java | 11 +- .../impl/MarkPassingsJsonSerializer.java | 7 +- .../impl/RaceEntriesJsonSerializer.java | 13 +-- .../jaxrs/api/CompetitorsResource.java | 9 +- .../jaxrs/api/LeaderboardsResource.java | 4 +- .../gateway/jaxrs/api/RegattasResource.java | 11 +- .../tracking/app/utils/CheckinManager.java | 1 + 20 files changed, 165 insertions(+), 244 deletions(-) delete mode 100644 java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java delete mode 100644 java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java index 8242ac9576b..f1260084aa1 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorJsonDeserializer.java @@ -11,6 +11,7 @@ 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.SharedDomainFactory; +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; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; @@ -21,23 +22,24 @@ import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.RGBColor; public class CompetitorJsonDeserializer implements JsonDeserializer { - private final CompetitorFactory competitorFactory; + private final CompetitorFactory competitorWithBoatFactory; private final JsonDeserializer teamJsonDeserializer; - + private final JsonDeserializer boatJsonDeserializer; private static final Logger logger = Logger.getLogger(CompetitorJsonDeserializer.class.getName()); public static CompetitorJsonDeserializer create(SharedDomainFactory baseDomainFactory) { return new CompetitorJsonDeserializer(baseDomainFactory, new TeamJsonDeserializer(new PersonJsonDeserializer( - new NationalityJsonDeserializer(baseDomainFactory)))); + new NationalityJsonDeserializer(baseDomainFactory))), new BoatJsonDeserializer(baseDomainFactory, new BoatClassJsonDeserializer(baseDomainFactory))); } - public CompetitorJsonDeserializer(CompetitorFactory competitorFactory) { - this(competitorFactory, null); + public CompetitorJsonDeserializer(CompetitorFactory competitorWithBoatFactory) { + this(competitorWithBoatFactory, null, /* boatDeserializer */ null); } - public CompetitorJsonDeserializer(CompetitorFactory competitorFactory, JsonDeserializer teamJsonDeserializer) { - this.competitorFactory = competitorFactory; + public CompetitorJsonDeserializer(CompetitorFactory competitorWithBoatFactory, JsonDeserializer teamJsonDeserializer, JsonDeserializer boatDeserializer) { + this.competitorWithBoatFactory = competitorWithBoatFactory; this.teamJsonDeserializer = teamJsonDeserializer; + this.boatJsonDeserializer = boatDeserializer; } @Override @@ -66,7 +68,6 @@ public class CompetitorJsonDeserializer implements JsonDeserializer logger.warning("Illegal flag image URI " + e.getMessage()); } } - final Color displayColor; if (displayColorAsString == null || displayColorAsString.isEmpty()) { displayColor = null; @@ -74,18 +75,31 @@ public class CompetitorJsonDeserializer implements JsonDeserializer displayColor = new RGBColor(displayColorAsString); } DynamicTeam team = null; + DynamicBoat boat = null; if (teamJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_TEAM) != null) { team = teamJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object, CompetitorJsonConstants.FIELD_TEAM)); } + if (boatJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_BOAT) != null) { + boat = boatJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object, + CompetitorJsonConstants.FIELD_BOAT)); + } final Double timeOnTimeFactor = (Double) object.get(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR); final Double timeOnDistanceAllowanceInSecondsPerNauticalMile = (Double) object .get(CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE); - Competitor competitor = competitorFactory.getOrCreateCompetitor(competitorId, name, shortName, displayColor, email, - flagImageURI, team, timeOnTimeFactor, - timeOnDistanceAllowanceInSecondsPerNauticalMile == null ? null : - new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag); - return competitor; + final Competitor result; + if (boat == null) { + result = competitorWithBoatFactory.getOrCreateCompetitor(competitorId, name, shortName, displayColor, email, + flagImageURI, team, timeOnTimeFactor, + timeOnDistanceAllowanceInSecondsPerNauticalMile == null ? null : + new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag); + } else { + result = competitorWithBoatFactory.getOrCreateCompetitorWithBoat(competitorId, name, shortName, displayColor, email, + flagImageURI, team, timeOnTimeFactor, + timeOnDistanceAllowanceInSecondsPerNauticalMile == null ? null : + new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag, boat); + } + return result; } catch (Exception e) { throw new JsonDeserializationException(e); } 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 deleted file mode 100644 index ea74b819490..00000000000 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorWithBoatJsonDeserializer.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.sap.sailing.server.gateway.deserialization.impl; - -import java.io.Serializable; -import java.lang.reflect.Constructor; -import java.net.URI; -import java.util.UUID; -import java.util.logging.Logger; - -import org.json.simple.JSONObject; - -import com.sap.sailing.domain.base.CompetitorFactory; -import com.sap.sailing.domain.base.CompetitorWithBoat; -import com.sap.sailing.domain.base.SharedDomainFactory; -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; -import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; -import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; -import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; -import com.sap.sse.common.Color; -import com.sap.sse.common.impl.MillisecondsDurationImpl; -import com.sap.sse.common.impl.RGBColor; - -public class CompetitorWithBoatJsonDeserializer implements JsonDeserializer { - private final CompetitorFactory competitorWithBoatFactory; - private final JsonDeserializer teamJsonDeserializer; - private final JsonDeserializer boatJsonDeserializer; - private static final Logger logger = Logger.getLogger(CompetitorWithBoatJsonDeserializer.class.getName()); - - public static CompetitorWithBoatJsonDeserializer create(SharedDomainFactory baseDomainFactory) { - return new CompetitorWithBoatJsonDeserializer(baseDomainFactory, new TeamJsonDeserializer(new PersonJsonDeserializer( - new NationalityJsonDeserializer(baseDomainFactory))), new BoatJsonDeserializer(baseDomainFactory, new BoatClassJsonDeserializer(baseDomainFactory))); - } - - public CompetitorWithBoatJsonDeserializer(CompetitorFactory competitorWithBoatFactory) { - this(competitorWithBoatFactory, null, /* boatDeserializer */ null); - } - - public CompetitorWithBoatJsonDeserializer(CompetitorFactory competitorWithBoatFactory, JsonDeserializer teamJsonDeserializer, JsonDeserializer boatDeserializer) { - this.competitorWithBoatFactory = competitorWithBoatFactory; - this.teamJsonDeserializer = teamJsonDeserializer; - this.boatJsonDeserializer = boatDeserializer; - } - - @Override - public CompetitorWithBoat deserialize(JSONObject object) throws JsonDeserializationException { - Serializable competitorId = (Serializable) object.get(CompetitorJsonSerializer.FIELD_ID); - try { - Class idClass = Class.forName((String) object.get(CompetitorJsonConstants.FIELD_ID_TYPE)); - if (Number.class.isAssignableFrom(idClass)) { - Constructor constructorFromString = idClass.getConstructor(String.class); - competitorId = (Serializable) constructorFromString.newInstance(competitorId.toString()); - } else if (UUID.class.isAssignableFrom(idClass)) { - competitorId = Helpers.tryUuidConversion(competitorId); - } - String name = (String) object.get(CompetitorJsonConstants.FIELD_NAME); - String shortName = (String) object.get(CompetitorJsonConstants.FIELD_SHORT_NAME); - String displayColorAsString = (String) object.get(CompetitorJsonConstants.FIELD_DISPLAY_COLOR); - String email = (String) object.get(CompetitorJsonConstants.FIELD_EMAIL); - String searchTag = (String) object.get(CompetitorJsonConstants.FIELD_SEARCHTAG); - - URI flagImageURI = null; - String flagImageURIAsString = (String) object.get(CompetitorJsonConstants.FIELD_FLAG_IMAGE_URI); - if (flagImageURIAsString != null) { - try { - flagImageURI = URI.create(flagImageURIAsString); - } catch (IllegalArgumentException e) { - logger.warning("Illegal flag image URI " + e.getMessage()); - } - } - - final Color displayColor; - if (displayColorAsString == null || displayColorAsString.isEmpty()) { - displayColor = null; - } else { - displayColor = new RGBColor(displayColorAsString); - } - DynamicTeam team = null; - DynamicBoat boat = null; - if (teamJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_TEAM) != null) { - team = teamJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object, - CompetitorJsonConstants.FIELD_TEAM)); - } - if (boatJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_BOAT) != null) { - boat = boatJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object, - CompetitorJsonConstants.FIELD_BOAT)); - String sailID = (String) object.get(CompetitorJsonConstants.FIELD_SAIL_ID); - boat.setSailId(sailID); - } - final Double timeOnTimeFactor = (Double) object.get(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR); - final Double timeOnDistanceAllowanceInSecondsPerNauticalMile = (Double) object - .get(CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE); - CompetitorWithBoat competitorWithBoat = competitorWithBoatFactory.getOrCreateCompetitorWithBoat(competitorId, name, shortName, displayColor, email, - flagImageURI, team, timeOnTimeFactor, - timeOnDistanceAllowanceInSecondsPerNauticalMile == null ? null : - new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile*1000)), searchTag, boat); - - return competitorWithBoat; - } catch (Exception e) { - throw new JsonDeserializationException(e); - } - } -} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LegacyCompetitorWithContainedBoatJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LegacyCompetitorWithContainedBoatJsonDeserializer.java index 3fb9f7221aa..bf7e1d34e28 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LegacyCompetitorWithContainedBoatJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LegacyCompetitorWithContainedBoatJsonDeserializer.java @@ -85,13 +85,10 @@ public class LegacyCompetitorWithContainedBoatJsonDeserializer implements JsonDe if (boatJsonDeserializer != null && object.get(CompetitorJsonConstants.FIELD_BOAT) != null) { boat = boatJsonDeserializer.deserialize(Helpers.getNestedObjectSafe(object, CompetitorJsonConstants.FIELD_BOAT)); - String sailID = (String) object.get(CompetitorJsonConstants.FIELD_SAIL_ID); - boat.setSailId(sailID); } final Double timeOnTimeFactor = (Double) object.get(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR); final Double timeOnDistanceAllowanceInSecondsPerNauticalMile = (Double) object .get(CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE); - CompetitorWithBoat competitorWithBoat = new CompetitorWithBoatImpl(competitorId, name, shortName, displayColor, email, flagImageURI, team, timeOnTimeFactor, timeOnDistanceAllowanceInSecondsPerNauticalMile == null ? null : diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java index 3477ce46d7d..bac24d4728c 100755 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEventDeserializer.java @@ -4,7 +4,6 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.SharedDomainFactory; import com.sap.sailing.domain.common.DeviceIdentifier; import com.sap.sailing.domain.racelogtracking.SmartphoneUUIDIdentifier; @@ -17,7 +16,6 @@ import com.sap.sailing.server.gateway.deserialization.coursedata.impl.MarkDeseri import com.sap.sailing.server.gateway.deserialization.coursedata.impl.WaypointDeserializer; 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.DeviceIdentifierJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.PositionJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.WindJsonDeserializer; @@ -58,7 +56,6 @@ public class RaceLogEventDeserializer 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), @@ -82,7 +79,7 @@ public class RaceLogEventDeserializer implements JsonDeserializer new RaceLogDenoteForTrackingEventDeserializer(competitorDeserializer, domainFactory), new RaceLogStartTrackingEventDeserializer(competitorDeserializer), new RaceLogRevokeEventDeserializer(competitorDeserializer), - new RaceLogRegisterCompetitorEventDeserializer(competitorDeserializer, competitorWithBoatDeserializer, BoatJsonDeserializer.create(domainFactory)), + new RaceLogRegisterCompetitorEventDeserializer(competitorDeserializer, BoatJsonDeserializer.create(domainFactory)), new RaceLogAdditionalScoringInformationEventDeserializer(competitorDeserializer), new RaceLogFixedMarkPassingEventDeserializer(competitorDeserializer), new RaceLogSuppressedMarkPassingsEventDeserializer(competitorDeserializer), 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 ede21992220..734df7cbbeb 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 @@ -10,7 +10,6 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; 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.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.BoatJsonDeserializer; @@ -18,30 +17,26 @@ import com.sap.sailing.server.gateway.serialization.racelog.impl.RaceLogRegister import com.sap.sse.common.TimePoint; public class RaceLogRegisterCompetitorEventDeserializer extends BaseRaceLogEventDeserializer { - private final JsonDeserializer competitorWithBoatDeserializer; private final BoatJsonDeserializer boatDeserializer; public RaceLogRegisterCompetitorEventDeserializer(JsonDeserializer competitorDeserializer, - JsonDeserializer competitorWithBoatDeserializer, BoatJsonDeserializer boatDeserializer) { + BoatJsonDeserializer boatDeserializer) { super(competitorDeserializer); - this.competitorWithBoatDeserializer = competitorWithBoatDeserializer; this.boatDeserializer = boatDeserializer; } @Override - protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { + 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"; - JSONObject competitorWithBoatObject = (JSONObject) object.get(RaceLogRegisterCompetitorEventSerializer.FIELD_COMPETITOR_WITHBOAT); - if (competitorWithBoatObject != null) { - CompetitorWithBoat competitorWithBoat = competitorWithBoatDeserializer.deserialize(competitorWithBoatObject); - return new RaceLogRegisterCompetitorEventImpl(createdAt, timePoint, author, id, passId, competitorWithBoat); - } else { - JSONObject competitorObject = (JSONObject) object.get(RaceLogRegisterCompetitorEventSerializer.FIELD_COMPETITOR); - JSONObject boatObject = (JSONObject) object.get(RaceLogRegisterCompetitorEventSerializer.FIELD_BOAT); - Competitor competitor = competitorDeserializer.deserialize(competitorObject); - Boat boat = boatDeserializer.deserialize(boatObject); - return new RaceLogRegisterCompetitorEventImpl(createdAt, timePoint, author, id, passId, competitor, boat); - } + JSONObject competitorObject = (JSONObject) (object + .get(RaceLogRegisterCompetitorEventSerializer.FIELD_COMPETITOR_WITHBOAT) != null + ? object.get(RaceLogRegisterCompetitorEventSerializer.FIELD_COMPETITOR_WITHBOAT) + : object.get(RaceLogRegisterCompetitorEventSerializer.FIELD_COMPETITOR)); + JSONObject boatObject = (JSONObject) object.get(RaceLogRegisterCompetitorEventSerializer.FIELD_BOAT); + Competitor competitor = competitorDeserializer.deserialize(competitorObject); + Boat boat = boatDeserializer.deserialize(boatObject); + return new RaceLogRegisterCompetitorEventImpl(createdAt, timePoint, author, id, passId, competitor, boat); } - } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java index 0edc3248d00..22693413521 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorJsonSerializer.java @@ -17,14 +17,37 @@ import com.sap.sailing.server.gateway.serialization.JsonSerializer; import com.sap.sse.common.Color; import com.sap.sse.common.CountryCode; +/** + * Serializes a {@link Competitor} or {@link CompetitorWithBoat} object. If a {@link CompetitorWithBoat} object, + * the {@link CompetitorJsonConstants#FIELD_BOAT} field will be filled with a boat document as serialized by the + * {@link BoatJsonSerializer}. For {@link Competitor} objects with {@link Competitor#hasBoat()}{@code == false} the + * {@link CompetitorJsonConstants#FIELD_BOAT} field will not be set. This can also be used by the corresponding + * de-serializer to identify which class implementing the {@link Competitor} interface to instantiate. + */ public class CompetitorJsonSerializer implements JsonSerializer { public static final String FIELD_ID = "id"; private final JsonSerializer teamJsonSerializer; private final JsonSerializer boatJsonSerializer; + /** + * Creates a serializer for {@link Competitor} objects which by default, if the competitor + * {@link Competitor#hasBoat() has a boat attached} will serialize the boat in the + * {@link CompetitorJsonConstants#FIELD_BOAT} field of the resulting document. See {@link #create(boolean)} for a + * variant where callers can choose whether the {@link CompetitorJsonConstants#FIELD_BOAT} field shall be filled or + * not. + */ public static CompetitorJsonSerializer create() { - return new CompetitorJsonSerializer(TeamJsonSerializer.create(), BoatJsonSerializer.create()); + return create(/* serialize boat */ true); + } + + /** + * Creates a serializer for {@link Competitor} objects which if {@code serializeBoat==true} and if the competitor + * {@link Competitor#hasBoat() has a boat attached} will serialize the boat in the + * {@link CompetitorJsonConstants#FIELD_BOAT} field of the resulting document. + */ + public static CompetitorJsonSerializer create(boolean serializeBoat) { + return new CompetitorJsonSerializer(TeamJsonSerializer.create(), serializeBoat?BoatJsonSerializer.create():null); } public CompetitorJsonSerializer() { diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java deleted file mode 100644 index 5750b0d9ab2..00000000000 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatJsonSerializer.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.sap.sailing.server.gateway.serialization.impl; - -import org.json.simple.JSONObject; - -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorWithBoat; -import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; -import com.sap.sailing.server.gateway.serialization.JsonSerializer; - -public class CompetitorWithBoatJsonSerializer implements JsonSerializer { - private final JsonSerializer boatJsonSerializer; - private final JsonSerializer competitorJsonSerializer; - - public static CompetitorWithBoatJsonSerializer create() { - return new CompetitorWithBoatJsonSerializer(CompetitorJsonSerializer.create(), BoatJsonSerializer.create()); - } - - public CompetitorWithBoatJsonSerializer(JsonSerializer competitorJsonSerializer, JsonSerializer boatJsonSerializer) { - this.competitorJsonSerializer = competitorJsonSerializer; - this.boatJsonSerializer = boatJsonSerializer; - } - - @Override - public JSONObject serialize(CompetitorWithBoat competitor) { - JSONObject serializedCompetitor = competitorJsonSerializer.serialize(competitor); - serializedCompetitor.put(CompetitorJsonConstants.FIELD_SAIL_ID, competitor.getBoat() == null ? "" : competitor.getBoat().getSailID()); - 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/impl/CompetitorWithBoatRefJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatRefJsonSerializer.java index 375c45008c5..c138c8a5ffb 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatRefJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/CompetitorWithBoatRefJsonSerializer.java @@ -12,7 +12,7 @@ public class CompetitorWithBoatRefJsonSerializer implements JsonSerializer competitorJsonSerializer; public static CompetitorWithBoatRefJsonSerializer create() { - return new CompetitorWithBoatRefJsonSerializer(CompetitorJsonSerializer.create()); + return new CompetitorWithBoatRefJsonSerializer(CompetitorJsonSerializer.create(/* serialize boat */ false)); } public CompetitorWithBoatRefJsonSerializer(JsonSerializer competitorJsonSerializer) { @@ -22,7 +22,6 @@ public class CompetitorWithBoatRefJsonSerializer implements JsonSerializer, Rac new RaceLogDenoteForTrackingEventSerializer(competitorSerializer), new RaceLogStartTrackingEventSerializer(competitorSerializer), new RaceLogRevokeEventSerializer(competitorSerializer), - new RaceLogRegisterCompetitorEventSerializer(competitorSerializer, CompetitorWithBoatJsonSerializer.create(), BoatJsonSerializer.create()), + new RaceLogRegisterCompetitorEventSerializer(competitorSerializer, BoatJsonSerializer.create()), new RaceLogAdditionalScoringInformationSerializer(competitorSerializer), new RaceLogFixedMarkPassingEventSerializer(competitorSerializer), new RaceLogSuppressedMarkPassingsEventSerializer(competitorSerializer), diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterCompetitorEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterCompetitorEventSerializer.java index ea62ed472d6..1ae684acba7 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterCompetitorEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogRegisterCompetitorEventSerializer.java @@ -6,24 +6,32 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; 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.sailing.domain.common.tracking.impl.CompetitorJsonConstants; 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.CompetitorWithBoatJsonSerializer; public class RaceLogRegisterCompetitorEventSerializer extends BaseRaceLogEventSerializer { public static final String VALUE_CLASS = RegisterCompetitorEvent.class.getSimpleName(); + + /** + * The following had been introduced temporarily during the development and initial deployment of + * bug2822. However, during subsequent cleanup activities the distinction between competitors with + * and without boat happens through the presence or absence, respectively, of the {@link CompetitorJsonConstants#FIELD_BOAT} + * field in the JSON document. Hence, a separate field is no longer needed. Only for backward compatibility + * for the rare case that some installation produced events with this field name does the field need to + * be preserved. + */ public static final String FIELD_COMPETITOR_WITHBOAT = "competitorWithBoat"; + public static final String FIELD_COMPETITOR = "competitor"; + public static final String FIELD_BOAT = "boat"; - private final CompetitorWithBoatJsonSerializer competitorWithBoatSerializer; private final BoatJsonSerializer boatSerializer; public RaceLogRegisterCompetitorEventSerializer(JsonSerializer competitorSerializer, - CompetitorWithBoatJsonSerializer competitorWithBoatSerializer, BoatJsonSerializer boatSerializer) { + BoatJsonSerializer boatSerializer) { super(competitorSerializer); - this.competitorWithBoatSerializer = competitorWithBoatSerializer; this.boatSerializer = boatSerializer; } @@ -35,16 +43,9 @@ public class RaceLogRegisterCompetitorEventSerializer extends BaseRaceLogEventSe @Override public JSONObject serialize(RaceLogEvent object) { RaceLogRegisterCompetitorEvent registerCompetitorEvent = (RaceLogRegisterCompetitorEvent) object; - JSONObject result = super.serialize(registerCompetitorEvent); - if (registerCompetitorEvent.getCompetitor().hasBoat()) { - CompetitorWithBoat competitorWithBoat = (CompetitorWithBoat) registerCompetitorEvent.getCompetitor(); - result.put(FIELD_COMPETITOR_WITHBOAT, competitorWithBoatSerializer.serialize(competitorWithBoat)); - } else { - result.put(FIELD_COMPETITOR, competitorSerializer.serialize(registerCompetitorEvent.getCompetitor())); - result.put(FIELD_BOAT, boatSerializer.serialize(registerCompetitorEvent.getBoat())); - } - + result.put(FIELD_COMPETITOR, competitorSerializer.serialize(registerCompetitorEvent.getCompetitor())); + result.put(FIELD_BOAT, boatSerializer.serialize(registerCompetitorEvent.getBoat())); return result; } } diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/CompetitorJsonSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/CompetitorJsonSerializerTest.java index b9075417471..fef0d5a11ed 100755 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/CompetitorJsonSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/CompetitorJsonSerializerTest.java @@ -1,9 +1,12 @@ package com.sap.sailing.server.gateway.serialization.test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.util.Collections; import java.util.UUID; import org.json.simple.JSONObject; @@ -12,9 +15,13 @@ import org.json.simple.parser.ParseException; import org.junit.Before; import org.junit.Test; +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.Team; +import com.sap.sailing.domain.base.impl.DomainFactoryImpl; +import com.sap.sailing.domain.base.impl.TransientCompetitorStoreImpl; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer; import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; @@ -28,9 +35,17 @@ public class CompetitorJsonSerializerTest { @Before public void setUp() { competitor = mock(Competitor.class); - when(competitor.getTeam()).thenReturn(mock(Team.class)); - serializer = new CompetitorJsonSerializer(); - deserializer = new CompetitorJsonDeserializer(DomainFactory.INSTANCE.getCompetitorStore()); + mockTeam(competitor); + serializer = CompetitorJsonSerializer.create(); + // use a separate competitor store for the de-serializer + deserializer = CompetitorJsonDeserializer.create(new DomainFactoryImpl(new TransientCompetitorStoreImpl(), /* raceLogResolver */ null)); + } + + private void mockTeam(final Competitor competitor) { + final Team team = mock(Team.class); + when(team.getSailors()).thenReturn(Collections.emptySet()); + when(team.getName()).thenReturn("The Team"); + when(competitor.getTeam()).thenReturn(team); } /** @@ -40,7 +55,6 @@ public class CompetitorJsonSerializerTest { public void testIntegerId() throws JsonDeserializationException, ParseException { Integer expectedId = Integer.valueOf(123); when(competitor.getId()).thenReturn(expectedId); - JSONObject result = serializer.serialize(competitor); assertEquals( expectedId, @@ -53,7 +67,6 @@ public class CompetitorJsonSerializerTest { public void testStringId() throws JsonDeserializationException, ParseException { String expectedId = "123"; when(competitor.getId()).thenReturn(expectedId); - JSONObject result = serializer.serialize(competitor); assertEquals( expectedId, @@ -62,6 +75,41 @@ public class CompetitorJsonSerializerTest { assertEquals(expectedId, deserializedCompetitor.getId()); } + @Test + public void testCompetitorWithBoat() throws JsonDeserializationException, ParseException { + final CompetitorWithBoat competitorWithBoat = mock(CompetitorWithBoat.class); + mockTeam(competitorWithBoat); + String expectedId = "123"; + when(competitorWithBoat.getId()).thenReturn(expectedId); + final Boat boat = mock(Boat.class); + when(competitorWithBoat.hasBoat()).thenReturn(true); + when(competitorWithBoat.getBoat()).thenReturn(boat); + when(boat.getId()).thenReturn(UUID.randomUUID()); + when(boat.getSailID()).thenReturn("1233"); + when(boat.getBoatClass()).thenReturn(DomainFactory.INSTANCE.getOrCreateBoatClass("Tornado")); + JSONObject result = serializer.serialize(competitorWithBoat); + final Competitor deserializedCompetitor = deserializer.deserialize((JSONObject) new JSONParser().parse(result.toString())); + assertTrue(deserializedCompetitor.hasBoat()); + assertTrue(deserializedCompetitor instanceof CompetitorWithBoat); + final CompetitorWithBoat deserializedCompetitorWithBoat = (CompetitorWithBoat) deserializedCompetitor; + assertEquals(boat.getId(), deserializedCompetitorWithBoat.getBoat().getId()); + assertEquals(boat.getSailID(), deserializedCompetitorWithBoat.getBoat().getSailID()); + } + + @Test + public void testCompetitorWithNullBoat() throws JsonDeserializationException, ParseException { + final CompetitorWithBoat competitorWithBoat = mock(CompetitorWithBoat.class); + mockTeam(competitorWithBoat); + String expectedId = "1234"; + when(competitorWithBoat.getId()).thenReturn(expectedId); + when(competitorWithBoat.hasBoat()).thenReturn(false); + when(competitorWithBoat.getBoat()).thenReturn(null); + JSONObject result = serializer.serialize(competitorWithBoat); + Competitor deserializedCompetitor = deserializer.deserialize((JSONObject) new JSONParser().parse(result.toString())); + assertFalse(deserializedCompetitor.hasBoat()); + assertFalse(deserializedCompetitor instanceof CompetitorWithBoat); + } + @Test public void testUUIDId() throws JsonDeserializationException, ParseException { UUID expectedId = UUID.randomUUID(); 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 02e4417b2d4..0879e7709d9 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 @@ -52,8 +52,7 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { SharedDomainFactory factory = DomainFactory.INSTANCE; serializer = new RaceLogFinishPositioningConfirmedEventSerializer(new CompetitorJsonSerializer( new TeamJsonSerializer(new PersonJsonSerializer(new NationalityJsonSerializer())), new BoatJsonSerializer(new BoatClassJsonSerializer()))); - deserializer = new RaceLogFinishPositioningConfirmedEventDeserializer(new CompetitorJsonDeserializer(factory.getCompetitorStore(), null)); - + deserializer = new RaceLogFinishPositioningConfirmedEventDeserializer(new CompetitorJsonDeserializer(factory.getCompetitorStore(), /* team deserializer */ null, /* boat deserializer */ null)); now = MillisecondsTimePoint.now(); positioningList = new CompetitorResultsImpl(); } @@ -73,9 +72,7 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { MaxPointsReason.NONE, /* score */ null, /* finishingTime */ null, /* comment */ null, MergeState.OK)); event = new RaceLogFinishPositioningConfirmedEventImpl(now, author, 0, positioningList); JSONObject jsonConfirmationEvent = serializer.serialize(event); - RaceLogFinishPositioningConfirmedEvent deserializedEvent = (RaceLogFinishPositioningConfirmedEvent) deserializer - .deserialize(jsonConfirmationEvent); - + RaceLogFinishPositioningConfirmedEvent deserializedEvent = (RaceLogFinishPositioningConfirmedEvent) deserializer.deserialize(jsonConfirmationEvent); assertEquals(event.getId(), deserializedEvent.getId()); assertEquals(event.getPassId(), deserializedEvent.getPassId()); assertEquals(event.getLogicalTimePoint(), deserializedEvent.getLogicalTimePoint()); @@ -92,9 +89,7 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { throws JsonDeserializationException { event = new RaceLogFinishPositioningConfirmedEventImpl(now, author, 0, null); JSONObject jsonConfirmationEvent = serializer.serialize(event); - RaceLogFinishPositioningConfirmedEvent deserializedEvent = (RaceLogFinishPositioningConfirmedEvent) deserializer - .deserialize(jsonConfirmationEvent); - + RaceLogFinishPositioningConfirmedEvent deserializedEvent = (RaceLogFinishPositioningConfirmedEvent) deserializer.deserialize(jsonConfirmationEvent); assertEquals(event.getId(), deserializedEvent.getId()); assertEquals(event.getPassId(), deserializedEvent.getPassId()); assertEquals(event.getLogicalTimePoint(), deserializedEvent.getLogicalTimePoint()); @@ -110,9 +105,7 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { throws JsonDeserializationException { event = new RaceLogFinishPositioningConfirmedEventImpl(now, author, 0, positioningList); JSONObject jsonConfirmationEvent = serializer.serialize(event); - RaceLogFinishPositioningConfirmedEvent deserializedEvent = (RaceLogFinishPositioningConfirmedEvent) deserializer - .deserialize(jsonConfirmationEvent); - + RaceLogFinishPositioningConfirmedEvent deserializedEvent = (RaceLogFinishPositioningConfirmedEvent) deserializer.deserialize(jsonConfirmationEvent); assertEquals(event.getId(), deserializedEvent.getId()); assertEquals(event.getPassId(), deserializedEvent.getPassId()); assertEquals(event.getLogicalTimePoint(), deserializedEvent.getLogicalTimePoint()); 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 553e20432cc..8dbe237aa41 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 @@ -53,11 +53,9 @@ public class RaceLogWindFixEventSerializerTest { serializer = new RaceLogWindFixEventSerializer(new CompetitorJsonSerializer(new TeamJsonSerializer( new PersonJsonSerializer(new NationalityJsonSerializer())), new BoatJsonSerializer(new BoatClassJsonSerializer())), new WindJsonSerializer( new PositionJsonSerializer())); - deserializer = new RaceLogWindFixEventDeserializer(new CompetitorJsonDeserializer(factory.getCompetitorStore(), null), + deserializer = new RaceLogWindFixEventDeserializer(new CompetitorJsonDeserializer(factory.getCompetitorStore(), /* team deserializer */ null, /* boat deserializer */ null), new WindJsonDeserializer(new PositionJsonDeserializer())); - now = MillisecondsTimePoint.now(); - event = new RaceLogWindFixEventImpl(now, author, 0, createWindFix(), /* isMagnetic */ false); } @@ -65,13 +63,11 @@ public class RaceLogWindFixEventSerializerTest { public void testSerializeAndDeserializeRaceLogWindFixEvent() throws JsonDeserializationException { JSONObject jsonWindFixEvent = serializer.serialize(event); RaceLogWindFixEvent deserializedEvent = (RaceLogWindFixEvent) deserializer.deserialize(jsonWindFixEvent); - assertEquals(event.getId(), deserializedEvent.getId()); assertEquals(event.getPassId(), deserializedEvent.getPassId()); assertEquals(event.getLogicalTimePoint(), deserializedEvent.getLogicalTimePoint()); assertEquals(0, Util.size(event.getInvolvedCompetitors())); assertEquals(0, Util.size(deserializedEvent.getInvolvedCompetitors())); - compareWind(event.getWindFix(), deserializedEvent.getWindFix()); } @@ -93,5 +89,4 @@ public class RaceLogWindFixEventSerializerTest { SpeedWithBearing speedBearing = new KnotSpeedWithBearingImpl(10.4, bearing); return new WindImpl(position, now, speedBearing); } - } 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 c4bb45d2071..4c658d59fc7 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,22 +7,21 @@ 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.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; +import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public class ManeuversJsonSerializer extends AbstractTrackedRaceDataJsonSerializer { public final static String MANEUVERS = "maneuvers"; - private final CompetitorWithBoatJsonSerializer competitorSerializer; + private final CompetitorAndBoatJsonSerializer competitorAndBoatSerializer; private final ManeuverJsonSerializer maneuverSerializer; - public ManeuversJsonSerializer(CompetitorWithBoatJsonSerializer competitorSerializer, ManeuverJsonSerializer maneuverSerializer) { + public ManeuversJsonSerializer(CompetitorAndBoatJsonSerializer competitorSerializer, ManeuverJsonSerializer maneuverSerializer) { super(); - this.competitorSerializer = competitorSerializer; + this.competitorAndBoatSerializer = competitorSerializer; this.maneuverSerializer = maneuverSerializer; } @@ -36,7 +35,7 @@ public class ManeuversJsonSerializer extends AbstractTrackedRaceDataJsonSerializ Boat boat = competitorAndBoatEntry.getValue(); final JSONObject forCompetitorJson = new JSONObject(); byCompetitorJson.add(forCompetitorJson); - forCompetitorJson.put(COMPETITOR, competitorSerializer.serialize(new CompetitorWithBoatImpl(competitor, (DynamicBoat) boat))); + forCompetitorJson.put(COMPETITOR, competitorAndBoatSerializer.serialize(new Pair<>(competitor, 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 7e656c4fcc3..ce590c01ef0 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,10 +11,9 @@ 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.CompetitorWithBoatImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sse.common.Util.Pair; public class MarkPassingsJsonSerializer extends AbstractTrackedRaceDataJsonSerializer { public static final String ZERO_BASED_WAYPOINT_INDEX = "zeroBasedWaypointIndex"; @@ -27,7 +26,7 @@ public class MarkPassingsJsonSerializer extends AbstractTrackedRaceDataJsonSeria public JSONObject serialize(TrackedRace trackedRace) { final Course course = trackedRace.getRace().getCourse(); JSONObject result = new JSONObject(); - CompetitorWithBoatJsonSerializer competitorWithBoatSerializer = CompetitorWithBoatJsonSerializer.create(); + CompetitorAndBoatJsonSerializer competitorWithBoatSerializer = CompetitorAndBoatJsonSerializer.create(); CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create(); JSONArray byCompetitorJson = new JSONArray(); result.put(BYCOMPETITOR, byCompetitorJson); @@ -36,7 +35,7 @@ public class MarkPassingsJsonSerializer extends AbstractTrackedRaceDataJsonSeria Boat boat = competitorAndBoatEntry.getValue(); JSONObject forCompetitorJson = new JSONObject(); byCompetitorJson.add(forCompetitorJson); - forCompetitorJson.put(COMPETITOR, competitorWithBoatSerializer.serialize(new CompetitorWithBoatImpl(competitor, (DynamicBoat) boat))); + forCompetitorJson.put(COMPETITOR, competitorWithBoatSerializer.serialize(new Pair<>(competitor, 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 231fbec82a3..17862d991c4 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,32 @@ 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.CompetitorWithBoat; import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.server.gateway.serialization.JsonSerializer; +import com.sap.sse.common.Util.Pair; public class RaceEntriesJsonSerializer implements JsonSerializer { public static final String FIELD_NAME = "name"; public static final String FIELD_COMPETITORS = "competitors"; - private final JsonSerializer competitorWithBoatSerializer; + private final CompetitorAndBoatJsonSerializer competitorAndBoatSerializer; public RaceEntriesJsonSerializer() { this(null); } - public RaceEntriesJsonSerializer(JsonSerializer competitorWithBoatSerializer) { - this.competitorWithBoatSerializer = competitorWithBoatSerializer; + public RaceEntriesJsonSerializer(CompetitorAndBoatJsonSerializer competitorAndBoatSerializer) { + this.competitorAndBoatSerializer = competitorAndBoatSerializer; } public JSONObject serialize(RaceDefinition race) { JSONObject result = new JSONObject(); result.put(FIELD_NAME, race.getName()); - if(competitorWithBoatSerializer != null) { + if(competitorAndBoatSerializer != null) { JSONArray competitorsJson = new JSONArray(); for (Entry competitorAndBoatEntry: race.getCompetitorsAndTheirBoats().entrySet()) { - competitorsJson.add(competitorWithBoatSerializer.serialize(new CompetitorWithBoatImpl(competitorAndBoatEntry.getKey(), + competitorsJson.add(competitorAndBoatSerializer.serialize(new Pair<>(competitorAndBoatEntry.getKey(), (DynamicBoat) competitorAndBoatEntry.getValue()))); } result.put(FIELD_COMPETITORS, competitorsJson); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java index 7cf7572c234..78c0aaf07f2 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java @@ -26,6 +26,7 @@ import org.json.simple.JSONObject; 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.Nationality; import com.sap.sailing.domain.base.Team; import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; @@ -52,6 +53,9 @@ public class CompetitorsResource extends AbstractSailingServerResource { JSONObject json = new JSONObject(); json.put(CompetitorJsonConstants.FIELD_ID, competitor.getId().toString()); json.put(CompetitorJsonConstants.FIELD_NAME, competitor.getName()); + if (competitor.hasBoat()) { + json.put(CompetitorJsonConstants.FIELD_SAIL_ID, ((CompetitorWithBoat) competitor).getBoat().getSailID()); + } json.put(CompetitorJsonConstants.FIELD_SHORT_NAME, competitor.getShortName()); final Nationality nationality = competitor.getTeam().getNationality(); json.put(CompetitorJsonConstants.FIELD_NATIONALITY, nationality==null?null:nationality.getThreeLetterIOCAcronym()); @@ -89,26 +93,21 @@ public class CompetitorsResource extends AbstractSailingServerResource { @Path("{competitor-id}/team") public Response getTeam(@PathParam("competitor-id") String competitorId) { Competitor competitor = getService().getCompetitorStore().getExistingCompetitorByIdAsString(competitorId); - if (competitor == null) { return Response.status(Status.NOT_FOUND) .entity("Could not find a competitor with id '" + StringEscapeUtils.escapeHtml(competitorId) + "'.").type(MediaType.TEXT_PLAIN) .build(); } - Team team = competitor.getTeam(); - if (team == null) { return Response.status(Status.NOT_FOUND) .entity("Could not find a team associated with competitor '" + StringEscapeUtils.escapeHtml(competitorId) + "'.") .type(MediaType.TEXT_PLAIN).build(); } - TeamJsonSerializer teamJsonSerializer = new TeamJsonSerializer(new PersonJsonSerializer( new NationalityJsonSerializer())); JSONObject teamJson = teamJsonSerializer.serialize(team); String json = teamJson.toJSONString(); - return Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java index 50980f2f49a..8a4d531e092 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java @@ -115,7 +115,7 @@ import com.sap.sailing.server.gateway.serialization.coursedata.impl.CourseJsonSe import com.sap.sailing.server.gateway.serialization.coursedata.impl.GateJsonSerializer; import com.sap.sailing.server.gateway.serialization.coursedata.impl.MarkJsonSerializer; import com.sap.sailing.server.gateway.serialization.coursedata.impl.WaypointJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.CompetitorWithBoatJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.FlatGPSFixJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.MarkJsonSerializerWithPosition; import com.sap.sse.InvalidDateException; @@ -1030,7 +1030,7 @@ public class LeaderboardsResource extends AbstractLeaderboardsResource { return result; }); } - CompetitorWithBoatJsonSerializer serializer = CompetitorWithBoatJsonSerializer.create(); + CompetitorJsonSerializer serializer = CompetitorJsonSerializer.create(); JSONArray result = new JSONArray(); for (final Competitor c : competitors) { Boat boat = trackedRace.getBoatOfCompetitor(c); 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 c7f4a8632fd..0646c518f5f 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 @@ -78,8 +78,8 @@ import com.sap.sailing.server.gateway.serialization.impl.AbstractTrackedRaceData import com.sap.sailing.server.gateway.serialization.impl.BoatClassJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.BoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.ColorJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorAndBoatJsonSerializer; 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.CompleteManeuverCurveWithEstimationDataJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.CompleteManeuverCurvesWithEstimationDataJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.DefaultWindTrackJsonSerializer; @@ -246,10 +246,9 @@ public class RegattasResource extends AbstractSailingServerResource { if (race == null) { response = getBadRaceErrorResponse(regattaName, raceName); } else { - CompetitorWithBoatJsonSerializer competitorJsonSerializer = CompetitorWithBoatJsonSerializer.create(); - JsonSerializer raceEntriesSerializer = new RaceEntriesJsonSerializer(competitorJsonSerializer); + CompetitorAndBoatJsonSerializer competitorAndBoatJsonSerializer = CompetitorAndBoatJsonSerializer.create(); + JsonSerializer raceEntriesSerializer = new RaceEntriesJsonSerializer(competitorAndBoatJsonSerializer); JSONObject serializedRaceEntries = raceEntriesSerializer.serialize(race); - String json = serializedRaceEntries.toJSONString(); response = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); } @@ -339,7 +338,7 @@ public class RegattasResource extends AbstractSailingServerResource { timeOnDistanceAllowancePerNauticalMileAsMillis == null ? null : new MillisecondsDurationImpl(timeOnDistanceAllowancePerNauticalMileAsMillis), searchTag, (DynamicBoat) boat); regatta.registerCompetitor(competitor); - response = Response.ok(CompetitorWithBoatJsonSerializer.create().serialize(competitor).toJSONString()). + response = Response.ok(CompetitorJsonSerializer.create().serialize(competitor).toJSONString()). header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); } return response; @@ -1014,7 +1013,7 @@ public class RegattasResource extends AbstractSailingServerResource { .build(); } else { TrackedRace trackedRace = findTrackedRace(regattaName, raceName); - ManeuversJsonSerializer serializer = new ManeuversJsonSerializer(CompetitorWithBoatJsonSerializer.create(), + ManeuversJsonSerializer serializer = new ManeuversJsonSerializer(CompetitorAndBoatJsonSerializer.create(), new ManeuverJsonSerializer(new GPSFixJsonSerializer(), new DistanceJsonSerializer())); JSONObject jsonMarkPassings = serializer.serialize(trackedRace); String json = jsonMarkPassings.toJSONString(); diff --git a/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/utils/CheckinManager.java b/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/utils/CheckinManager.java index 8f5528ff32c..907dc3045e4 100644 --- a/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/utils/CheckinManager.java +++ b/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/utils/CheckinManager.java @@ -246,6 +246,7 @@ public class CheckinManager { data.competitorName = response.getString(CompetitorJsonConstants.FIELD_NAME); data.competitorId = response.getString(CompetitorJsonConstants.FIELD_ID); data.competitorSailId = response.getString(CompetitorJsonConstants.FIELD_SAIL_ID); + // TODO read CompetitorJsonConstants.FIELD_SHORT_NAME and manage as an alternative to a non-existing sail ID data.competitorNationality = response.getString(CompetitorJsonConstants.FIELD_NATIONALITY); data.competitorCountryCode = response.getString(CompetitorJsonConstants.FIELD_COUNTRY_CODE); // TODO Bug 3358: get optional team image from CompetitorJsonConstants.FIELD_TEAM_IMAGE_URI From b0a366992496f7fc8aff119f4109959dbeaf119b Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Mon, 9 Apr 2018 17:01:44 +0200 Subject: [PATCH 2/5] use a CompetitorAndBoatJsonSerializer in LeaderboardsResource.getStartOrder() Change-Id: Ibf9dc7f2b57318f6696d5df3d119dc3a2a7fe62d --- .../server/gateway/jaxrs/api/LeaderboardsResource.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java index 8a4d531e092..32957aa9edf 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java @@ -64,9 +64,7 @@ import com.sap.sailing.domain.base.RaceColumn; 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.CompetitorWithBoatImpl; import com.sap.sailing.domain.base.impl.CourseImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.domain.common.Bearing; import com.sap.sailing.domain.common.CourseDesignerMode; import com.sap.sailing.domain.common.DeviceIdentifier; @@ -115,7 +113,7 @@ import com.sap.sailing.server.gateway.serialization.coursedata.impl.CourseJsonSe import com.sap.sailing.server.gateway.serialization.coursedata.impl.GateJsonSerializer; import com.sap.sailing.server.gateway.serialization.coursedata.impl.MarkJsonSerializer; import com.sap.sailing.server.gateway.serialization.coursedata.impl.WaypointJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorAndBoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.FlatGPSFixJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.MarkJsonSerializerWithPosition; import com.sap.sse.InvalidDateException; @@ -1030,11 +1028,11 @@ public class LeaderboardsResource extends AbstractLeaderboardsResource { return result; }); } - CompetitorJsonSerializer serializer = CompetitorJsonSerializer.create(); + CompetitorAndBoatJsonSerializer serializer = CompetitorAndBoatJsonSerializer.create(); JSONArray result = new JSONArray(); for (final Competitor c : competitors) { Boat boat = trackedRace.getBoatOfCompetitor(c); - JSONObject jsonCompetitor = serializer.serialize(new CompetitorWithBoatImpl(c, (DynamicBoat) boat)); + JSONObject jsonCompetitor = serializer.serialize(new Pair<>(c, boat)); result.add(jsonCompetitor); } String json = result.toJSONString(); From 9cfb66cbe832d48e752dcb615cc2c47e3d483e5e Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Mon, 9 Apr 2018 17:06:50 +0200 Subject: [PATCH 3/5] fixed RaceManager app's start order acquisition Change-Id: Ie287abcd78c8856476759724bed11c18674329c8 --- .../sailing/racecommittee/app/data/OnlineDataManager.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java index 5b3610a81d4..e7b06d40002 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java @@ -282,17 +282,15 @@ public class OnlineDataManager extends DataManager { JsonDeserializer> competitorAndBoatDeserializer = CompetitorAndBoatJsonDeserializer.create(domainFactory); DataParser> parser = new CompetitorsDataParser(competitorAndBoatDeserializer); DataHandler> handler = new CompetitorsDataHandler(OnlineDataManager.this, managedRace); - - // https://dev.sapsailing.com/sailingserver/api/v1/regattas/ESS%202016%20Cardiff/races/Race%2016/startorder Uri.Builder uri = Uri.parse(preferences.getServerBaseURL()).buildUpon(); uri.appendPath("sailingserver"); uri.appendPath("api"); uri.appendPath("v1"); - uri.appendPath("regattas"); + uri.appendPath("leaderboards"); uri.appendPath(managedRace.getIdentifier().getRaceGroup().getName()); - uri.appendPath("races"); - uri.appendPath(managedRace.getName()); uri.appendPath("startorder"); + uri.appendQueryParameter(RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME, managedRace.getIdentifier().getRaceColumnName()); + uri.appendQueryParameter(RaceLogServletConstants.PARAMS_RACE_FLEET_NAME, managedRace.getIdentifier().getFleet().getName()); return new OnlineDataLoader<>(context, new URL(uri.build().toString()), parser, handler); } }, getContext()); From e4e9cdb22c6685e0b7df0583998c00326adbf10d Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Mon, 9 Apr 2018 18:23:33 +0200 Subject: [PATCH 4/5] changed CompetitorAndBoat[De]Serializer such that it is backward compatible for CompetitorWithBoat Change-Id: Ia5717bdef5d9db7833b8d44df061dce524cecf85 --- .../CompetitorAndBoatJsonDeserializer.java | 13 +++- .../impl/CompetitorAndBoatJsonSerializer.java | 40 ++++++++--- .../test/CompetitorJsonSerializerTest.java | 67 +++++++++++++++++++ 3 files changed, 110 insertions(+), 10 deletions(-) diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorAndBoatJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorAndBoatJsonDeserializer.java index 1eb176b3e8a..70cb8de3489 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorAndBoatJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/CompetitorAndBoatJsonDeserializer.java @@ -4,6 +4,7 @@ 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.CompetitorWithBoat; import com.sap.sailing.domain.base.SharedDomainFactory; import com.sap.sailing.domain.base.impl.DynamicBoat; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; @@ -26,8 +27,16 @@ public class CompetitorAndBoatJsonDeserializer implements JsonDeserializer deserialize(JSONObject competitorAndBoatJsonObject) throws JsonDeserializationException { - Competitor competitor = competitorDeserializer.deserialize(Helpers.getNestedObjectSafe(competitorAndBoatJsonObject, CompetitorAndBoatJsonSerializer.FIELD_COMPETITOR)); - Boat boat = boatDeserializer.deserialize(Helpers.getNestedObjectSafe(competitorAndBoatJsonObject, CompetitorAndBoatJsonSerializer.FIELD_BOAT)); + final Competitor competitor; + final Boat boat; + if (competitorAndBoatJsonObject.containsKey(CompetitorAndBoatJsonSerializer.FIELD_COMPETITOR)) { + competitor = competitorDeserializer.deserialize(Helpers.getNestedObjectSafe(competitorAndBoatJsonObject, CompetitorAndBoatJsonSerializer.FIELD_COMPETITOR)); + boat = boatDeserializer.deserialize(Helpers.getNestedObjectSafe(competitorAndBoatJsonObject, CompetitorAndBoatJsonSerializer.FIELD_BOAT)); + } else { + final CompetitorWithBoat competitorWithBoat = (CompetitorWithBoat) competitorDeserializer.deserialize(competitorAndBoatJsonObject); + competitor = competitorWithBoat; + boat = competitorWithBoat.getBoat(); + } return new Pair(competitor, boat); } } 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/CompetitorAndBoatJsonSerializer.java index e0c7f3a2b8e..9f57a1f7fc2 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/CompetitorAndBoatJsonSerializer.java @@ -1,9 +1,12 @@ package com.sap.sailing.server.gateway.serialization.impl; +import java.util.logging.Logger; + 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.CompetitorWithBoat; import com.sap.sailing.server.gateway.serialization.JsonSerializer; import com.sap.sse.common.Util.Pair; @@ -11,6 +14,8 @@ import com.sap.sse.common.Util.Pair; * Serializes a competitor AND a boat as a kind of pair (e.g. in the context of a race) */ public class CompetitorAndBoatJsonSerializer implements JsonSerializer> { + private static final Logger logger = Logger.getLogger(CompetitorAndBoatJsonSerializer.class.getName()); + private final JsonSerializer competitorJsonSerializer; private final JsonSerializer boatJsonSerializer; @@ -28,14 +33,33 @@ public class CompetitorAndBoatJsonSerializer implements JsonSerializer competitorAndBoat) { - JSONObject serializedCompetitorAndBoat = new JSONObject(); - + final JSONObject result; JSONObject serializedCompetitor = competitorJsonSerializer.serialize(competitorAndBoat.getA()); - JSONObject serializedBoat = boatJsonSerializer.serialize(competitorAndBoat.getB()); - - serializedCompetitorAndBoat.put(FIELD_COMPETITOR, serializedCompetitor); - serializedCompetitorAndBoat.put(FIELD_BOAT, serializedBoat); - - return serializedCompetitorAndBoat; + // for compatibility, write a CompetitorWithBoat in the same format that a Competitor use to be + // serialized; only if the competitor has no boat, use the new format. The de-serializer will be + // able to distinguish based on the presence of the top-level FIELD_COMPETITOR field. + final boolean compatibilityMode; + if (competitorAndBoat.getA().hasBoat()) { + final CompetitorWithBoat competitorWithBoat = (CompetitorWithBoat) competitorAndBoat.getA(); + final Boat boat = competitorWithBoat.getBoat(); + if (boat != competitorAndBoat.getB()) { + logger.warning("Competitor "+competitorWithBoat+" has boat "+boat+" which is different from the boat to be serialized with it ("+ + competitorAndBoat.getB()); + compatibilityMode = false; + } else { + compatibilityMode = true; + } + } else { + compatibilityMode = false; + } + if (compatibilityMode) { + result = serializedCompetitor; + } else { + JSONObject serializedBoat = boatJsonSerializer.serialize(competitorAndBoat.getB()); + result = new JSONObject(); + result.put(FIELD_COMPETITOR, serializedCompetitor); + result.put(FIELD_BOAT, serializedBoat); + } + return result; } } diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/CompetitorJsonSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/CompetitorJsonSerializerTest.java index fef0d5a11ed..123ba94d632 100755 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/CompetitorJsonSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/CompetitorJsonSerializerTest.java @@ -2,6 +2,7 @@ package com.sap.sailing.server.gateway.serialization.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -23,8 +24,11 @@ import com.sap.sailing.domain.base.Team; import com.sap.sailing.domain.base.impl.DomainFactoryImpl; import com.sap.sailing.domain.base.impl.TransientCompetitorStoreImpl; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; +import com.sap.sailing.server.gateway.deserialization.impl.CompetitorAndBoatJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorAndBoatJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; +import com.sap.sse.common.Util.Pair; public class CompetitorJsonSerializerTest { @@ -96,6 +100,69 @@ public class CompetitorJsonSerializerTest { assertEquals(boat.getSailID(), deserializedCompetitorWithBoat.getBoat().getSailID()); } + @Test + public void testCompetitorAndBoatWithBoat() throws JsonDeserializationException, ParseException { + final CompetitorWithBoat competitorWithBoat = mock(CompetitorWithBoat.class); + mockTeam(competitorWithBoat); + String expectedId = "123"; + when(competitorWithBoat.getId()).thenReturn(expectedId); + final Boat boat = mock(Boat.class); + when(competitorWithBoat.hasBoat()).thenReturn(true); + when(competitorWithBoat.getBoat()).thenReturn(boat); + when(boat.getId()).thenReturn(UUID.randomUUID()); + when(boat.getSailID()).thenReturn("1233"); + when(boat.getBoatClass()).thenReturn(DomainFactory.INSTANCE.getOrCreateBoatClass("Tornado")); + JSONObject result = CompetitorAndBoatJsonSerializer.create().serialize(new Pair<>(competitorWithBoat, boat)); + final Pair deserializedCompetitorAndBoat = CompetitorAndBoatJsonDeserializer + .create(new DomainFactoryImpl(new TransientCompetitorStoreImpl(), /* raceLogResolver */ null)) + .deserialize((JSONObject) new JSONParser().parse(result.toString())); + assertTrue(deserializedCompetitorAndBoat.getA().hasBoat()); + assertTrue(deserializedCompetitorAndBoat.getA() instanceof CompetitorWithBoat); + final CompetitorWithBoat deserializedCompetitorWithBoat = (CompetitorWithBoat) deserializedCompetitorAndBoat.getA(); + assertSame(deserializedCompetitorWithBoat.getBoat(), deserializedCompetitorAndBoat.getB()); + assertEquals(boat.getId(), deserializedCompetitorWithBoat.getBoat().getId()); + assertEquals(boat.getSailID(), deserializedCompetitorWithBoat.getBoat().getSailID()); + } + + @Test + public void testCompetitorAndBoatWithoutBoat() throws JsonDeserializationException, ParseException { + String expectedId = "1234"; + when(competitor.getId()).thenReturn(expectedId); + when(competitor.hasBoat()).thenReturn(false); + final Boat boat = mock(Boat.class); + when(boat.getId()).thenReturn(UUID.randomUUID()); + when(boat.getSailID()).thenReturn("12334"); + when(boat.getBoatClass()).thenReturn(DomainFactory.INSTANCE.getOrCreateBoatClass("Tornado")); + JSONObject result = CompetitorAndBoatJsonSerializer.create().serialize(new Pair<>(competitor, boat)); + final Pair deserializedCompetitorAndBoat = CompetitorAndBoatJsonDeserializer + .create(new DomainFactoryImpl(new TransientCompetitorStoreImpl(), /* raceLogResolver */ null)) + .deserialize((JSONObject) new JSONParser().parse(result.toString())); + assertFalse(deserializedCompetitorAndBoat.getA().hasBoat()); + assertFalse(deserializedCompetitorAndBoat.getA() instanceof CompetitorWithBoat); + assertEquals("12334", deserializedCompetitorAndBoat.getB().getSailID()); + } + + @Test + public void testCompetitorAndBoatWithNullBoat() throws JsonDeserializationException, ParseException { + final CompetitorWithBoat competitorWithBoat = mock(CompetitorWithBoat.class); + mockTeam(competitorWithBoat); + String expectedId = "1234"; + when(competitorWithBoat.getId()).thenReturn(expectedId); + when(competitorWithBoat.hasBoat()).thenReturn(false); + when(competitorWithBoat.getBoat()).thenReturn(null); + final Boat boat = mock(Boat.class); + when(boat.getId()).thenReturn(UUID.randomUUID()); + when(boat.getSailID()).thenReturn("1233"); + when(boat.getBoatClass()).thenReturn(DomainFactory.INSTANCE.getOrCreateBoatClass("Tornado")); + JSONObject result = CompetitorAndBoatJsonSerializer.create().serialize(new Pair<>(competitorWithBoat, boat)); + final Pair deserializedCompetitorAndBoat = CompetitorAndBoatJsonDeserializer + .create(new DomainFactoryImpl(new TransientCompetitorStoreImpl(), /* raceLogResolver */ null)) + .deserialize((JSONObject) new JSONParser().parse(result.toString())); + assertFalse(deserializedCompetitorAndBoat.getA().hasBoat()); + assertFalse(deserializedCompetitorAndBoat.getA() instanceof CompetitorWithBoat); + assertEquals("1233", deserializedCompetitorAndBoat.getB().getSailID()); + } + @Test public void testCompetitorWithNullBoat() throws JsonDeserializationException, ParseException { final CompetitorWithBoat competitorWithBoat = mock(CompetitorWithBoat.class); From cfe4af7251944c0d8268ba6a865a7ca584393767 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Tue, 10 Apr 2018 18:43:07 +0200 Subject: [PATCH 5/5] added null checks for boat.getColor() in app code Change-Id: I3878752357eb0836f98b633d64366df7cefa20be --- .../gateway/serialization/impl/RegattaJsonSerializer.java | 8 ++------ .../android/tracking/app/utils/DatabaseHelper.java | 5 +---- .../app/ui/adapters/CompetitorAndBoatAdapter.java | 4 +++- .../racecommittee/app/ui/adapters/FinishListAdapter.java | 4 +++- .../racecommittee/app/ui/adapters/PenaltyAdapter.java | 4 +++- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RegattaJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RegattaJsonSerializer.java index d721f4f97ce..5f4a4192b0c 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RegattaJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/RegattaJsonSerializer.java @@ -33,30 +33,26 @@ public class RegattaJsonSerializer implements JsonSerializer { public JSONObject serialize(Regatta regatta) { JSONObject result = new JSONObject(); - result.put(FIELD_NAME, regatta.getName()); result.put(FIELD_START_DATE, regatta.getStartDate() != null ? regatta.getStartDate().asMillis() : null); result.put(FIELD_END_DATE, regatta.getEndDate() != null ? regatta.getEndDate().asMillis() : null); result.put(FIELD_SCORINGSYSTEM, regatta.getScoringScheme().getType().name()); result.put(FIELD_BOATCLASS, regatta.getBoatClass() != null ? regatta.getBoatClass().getName(): null); result.put(FIELD_COURSE_AREA_ID, regatta.getDefaultCourseArea() != null ? regatta.getDefaultCourseArea().getId().toString(): null); - - if(seriesSerializer != null) { + if (seriesSerializer != null) { JSONArray seriesJson = new JSONArray(); for (Series series : regatta.getSeries()) { seriesJson.add(seriesSerializer.serialize(series)); } result.put(FIELD_SERIES, seriesJson); } - - if(competitorSerializer != null) { + if (competitorSerializer != null) { JSONArray competitorsJson = new JSONArray(); for (Competitor competitor: regatta.getAllCompetitors()) { competitorsJson.add(competitorSerializer.serialize(competitor)); } result.put(FIELD_COMPETITORS, competitorsJson); } - return result; } } diff --git a/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/utils/DatabaseHelper.java b/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/utils/DatabaseHelper.java index 29964eeb8eb..47a7c924bd9 100644 --- a/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/utils/DatabaseHelper.java +++ b/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/utils/DatabaseHelper.java @@ -261,7 +261,6 @@ public class DatabaseHelper { LeaderboardInfo leaderboard = checkin.getLeaderboard(); CheckinUrlInfo checkinUrlInfo = checkin.getCheckinUrl(); Boat boat = checkin.getBoat(); - // boat ContentResolver contentResolver = context.getContentResolver(); ArrayList opList = new ArrayList<>(); @@ -273,11 +272,9 @@ public class DatabaseHelper { cv.put(AnalyticsContract.Boat.BOAT_NAME, boat.getName()); } cv.put(AnalyticsContract.Boat.BOAT_CHECKIN_DIGEST, checkinUrlInfo.checkinDigest); - cv.put(AnalyticsContract.Boat.BOAT_COLOR, boat.getColor().getAsHtml()); + cv.put(AnalyticsContract.Boat.BOAT_COLOR, boat.getColor()==null?null:boat.getColor().getAsHtml()); opList.add(ContentProviderOperation.newInsert(AnalyticsContract.Boat.CONTENT_URI).withValues(cv).build()); - addBasicInformationToOperationList(opList, leaderboard, event, checkinUrlInfo); - try { contentResolver.applyBatch(AnalyticsContract.CONTENT_AUTHORITY, opList); } catch (RemoteException | OperationApplicationException e) { diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/CompetitorAndBoatAdapter.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/CompetitorAndBoatAdapter.java index 71b9ceba3ff..eb1ba737af4 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/CompetitorAndBoatAdapter.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/adapters/CompetitorAndBoatAdapter.java @@ -44,7 +44,9 @@ public class CompetitorAndBoatAdapter extends RecyclerView.Adapter