From 52205ea7eedbed2580253e7361abc9e10f00c7d0 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 6 Dec 2018 16:02:06 +0100 Subject: [PATCH 1/2] added a BoatClassesResource Change-Id: Ie77872820e44439c8789d953a1ea6fad93a5ccec --- .../domain/base/SharedDomainFactory.java | 4 ++ .../base/impl/SharedDomainFactoryImpl.java | 33 ++++++++++-- .../jaxrs/api/BoatClassesResource.java | 51 +++++++++++++++++++ .../gateway/jaxrs/api/RestApiApplication.java | 1 + 4 files changed, 85 insertions(+), 4 deletions(-) create mode 100755 java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/BoatClassesResource.java 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 2ef5b4568c3..bb38989dd9d 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 @@ -73,6 +73,10 @@ public interface SharedDomainFactory extends CompetitorFactory, BoatFactory { */ Waypoint getExistingWaypointByIdOrCache(Waypoint waypoint); + BoatClass getBoatClass(String name); + + Iterable getBoatClasses(); + BoatClass getOrCreateBoatClass(String name, boolean typicallyStartsUpwind); /** 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 b66705f16ac..e1a91903c2f 100755 --- 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 @@ -292,9 +292,36 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { ((WeakWaypointReference) ref).removeCacheEntry(); } } + + @Override + public BoatClass getBoatClass(String name) { + return getBoatClassOrCreateIfMasterdataExists(name); + } + @Override + public Iterable getBoatClasses() { + return Collections.unmodifiableCollection(boatClassCache.values()); + } + @Override public BoatClass getOrCreateBoatClass(String name, boolean typicallyStartsUpwind) { + synchronized (boatClassCache) { + BoatClass result = getBoatClassOrCreateIfMasterdataExists(name); + if (result == null) { + final String unifiedBoatClassName = BoatClassMasterdata.unifyBoatClassNameBasedOnExistingMasterdata(name); + result = new BoatClassImpl(unifiedBoatClassName, typicallyStartsUpwind); + boatClassCache.put(unifiedBoatClassName, result); + } + return result; + } + } + + /** + * @return {@code null} if no master data is found for the boat class and the cache doesn't contain a boat class + * with the {@link BoatClassMasterdata#unifyBoatClassNameBasedOnExistingMasterdata(String)} unified / + * canonicalized name. + */ + private BoatClass getBoatClassOrCreateIfMasterdataExists(String name) { final BoatClassMasterdata boatClassMasterdata = BoatClassMasterdata.resolveBoatClass(name); final String unifiedBoatClassName = BoatClassMasterdata.unifyBoatClassNameBasedOnExistingMasterdata(name); BoatClass result; @@ -303,15 +330,13 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { if (result == null) { if (unifiedBoatClassName != null && boatClassMasterdata != null) { result = new BoatClassImpl(boatClassMasterdata.getDisplayName(), boatClassMasterdata); - } else { - result = new BoatClassImpl(unifiedBoatClassName, typicallyStartsUpwind); + boatClassCache.put(unifiedBoatClassName, result); } - boatClassCache.put(unifiedBoatClassName, result); } return result; } } - + @Override public BoatClass getOrCreateBoatClass(final String name) { final String unifiedBoatClassName = BoatClassMasterdata.unifyBoatClassNameBasedOnExistingMasterdata(name); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/BoatClassesResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/BoatClassesResource.java new file mode 100755 index 00000000000..dadaff88285 --- /dev/null +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/BoatClassesResource.java @@ -0,0 +1,51 @@ +package com.sap.sailing.server.gateway.jaxrs.api; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.lang.StringEscapeUtils; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; +import com.sap.sailing.server.gateway.serialization.impl.BoatClassJsonSerializer; + +@Path("/v1/boatclasses") +public class BoatClassesResource extends AbstractSailingServerResource { + + @GET + @Produces("application/json;charset=UTF-8") + public Response getBoatClasses() { + BoatClassJsonSerializer boatClassJsonSerializer = new BoatClassJsonSerializer(); + final JSONArray result = new JSONArray(); + for (final BoatClass boatClass : getService().getBaseDomainFactory().getBoatClasses()) { + final JSONObject jsonBoatClass = boatClassJsonSerializer.serialize(boatClass); + result.add(jsonBoatClass); + } + return Response.ok(result.toJSONString()).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); + } + + @GET + @Produces("application/json;charset=UTF-8") + @Path("{boatClassName}") + public Response getBoat(@PathParam("boatClassName") String boatClassName) { + Response response; + BoatClass boatClass = getService().getBaseDomainFactory().getBoatClass(boatClassName); + if (boatClass == null) { + response = Response.status(Status.NOT_FOUND) + .entity("Could not find a boat with id '" + StringEscapeUtils.escapeHtml(boatClassName) + "'.") + .type(MediaType.TEXT_PLAIN).build(); + } else { + BoatClassJsonSerializer boatClassJsonSerializer = new BoatClassJsonSerializer(); + String jsonString = boatClassJsonSerializer.serialize(boatClass).toJSONString(); + response = Response.ok(jsonString).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); + } + return response; + } +} diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java index 2d1bff7ef5d..6d9e9a3c5e4 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java @@ -16,6 +16,7 @@ public class RestApiApplication extends Application { classes.add(EventsResource.class); classes.add(RegattasResource.class); classes.add(BoatsResource.class); + classes.add(BoatClassesResource.class); classes.add(LeaderboardsResource.class); classes.add(LeaderboardsResourceV2.class); classes.add(PolarResource.class); From 9e9252de24199d983b2d0b1f48717a87bc646913 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 6 Dec 2018 16:22:10 +0100 Subject: [PATCH 2/2] added documentation on new boatclass REST end point Change-Id: I55e224cba69f7236dcc729f64c2f7672e0f7091c --- .../webservices/api/v1/boatclasses.html | 84 +++++++++++++++++++ .../webservices/api/v1/index.html | 4 + 2 files changed, 88 insertions(+) create mode 100755 java/com.sap.sailing.server.gateway/webservices/api/v1/boatclasses.html diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/boatclasses.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/boatclasses.html new file mode 100755 index 00000000000..dc3d775a990 --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/boatclasses.html @@ -0,0 +1,84 @@ + + + + + + + + SAP Sailing Analytics Webservices API Version 1.0 + + +

SAP Sailing Analytics Webservices API Version 1.0

+

URL: /api/v1/boatclasses

+ +Description: +

Gets information about a boat class or the list of available boat classes

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Webservice Type:REST
Output format:Json
Mandatory parameters:None
Optional parameters:boatclassname
Request method:GET
Example all boat classes:http://www.sapsailing.com/sailingserver/api/v1/boatclasses
Example answer
+     
+[
+{
+"name": "MANTRA28",
+"typicallyStartsUpwind": true
+},
+{
+"name": "30QMSCHÄRENKREUZER",
+"typicallyStartsUpwind": true
+},
+{
+"name": "75QMNATIONALEKREUZER",
+"typicallyStartsUpwind": true
+},
+...
+]
+
+    
+
Example specific boat class http://www.sapsailing.com/sailingserver/api/v1/boatclasses/MANTRA28
Example answer
+     
+{
+"name": "MANTRA28",
+"typicallyStartsUpwind": true
+}
+
+    
+
+Back to Web Service Overview + + diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html index 04202972b64..a6189041a7c 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html @@ -264,6 +264,10 @@ name to make sure you get to the event you're interested in. /api/v1/trackedRaces/raceDetails Gets more information about a specified RegattaAndRace identifier + + /api/v1/boatclasses + Obtains information about all or a single boat class + /api/v1/boats Obtains information about a single boat