add gpsfixes endpoint in REST API and update tracking app

This commit is contained in:
Fredrik Teschke committed 2014-11-16 20:13:28 +01:00
1 parent ebf4cc5fed
commit 4acf842890
7 files changed
+222 -24

No files matched your search

@@ -8,10 +8,10 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Fragment-Host: com.sap.sailing.server.gateway.serialization
Require-Bundle: com.sap.sailing.domain;bundle-version="1.0.0",
com.sap.sailing.domain.common;bundle-version="1.0.0",
org.hamcrest;bundle-version="1.1.0",
org.junit4;bundle-version="4.8.2",
com.sap.sailing.domain.shared.android,
org.json.simple,
org.mockito.mockito-core;bundle-version="1.9.5",
org.hamcrest;bundle-version="1.1.0",
org.objenesis;bundle-version="1.3.0",
com.sap.sse.common
@@ -0,0 +1,50 @@
package com.sap.sailing.server.gateway.serialization.test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import java.util.List;
import java.util.UUID;
import org.json.simple.JSONValue;
import org.json.simple.parser.ParseException;
import org.junit.Test;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
import com.sap.sse.common.Util.Pair;
public class FlatSmartphoneUuidAndGPSFixMovingJsonDeserializerTest {
@Test
public void deserialize() throws JsonDeserializationException, ParseException {
String json = "{\n" +
" \"deviceUuid\" : \"af855a56-9726-4a9c-a77e-da955bd289bf\",\n" +
" \"fixes\" : [\n" +
" {\n" +
" \"timestamp\" : 14144160080000,\n" +
" \"latitude\" : 54.325246,\n" +
" \"longitude\" : 10.148556,\n" +
" \"speed\" : 3.61,\n" +
" \"course\" : 258.11,\n" +
" },\n" +
" {\n" +
" \"timestamp\" : 14144168490000,\n" +
" \"latitude\" : 55.12456,\n" +
" \"longitude\" : 8.03456,\n" +
" \"speed\" : 5.1,\n" +
" \"course\" : 14.2,\n" +
" }\n" +
" ]\n" +
"}";
JsonDeserializer<Pair<UUID, List<GPSFixMoving>>> deserializer =
new FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer();
Pair<UUID, List<GPSFixMoving>> result =
deserializer.deserialize(Helpers.toJSONObjectSafe(JSONValue.parseWithException(json)));
assertThat("uuid", result.getA(), equalTo(UUID.fromString("af855a56-9726-4a9c-a77e-da955bd289bf")));
assertThat("number of fixes", result.getB().size(), equalTo(2));
}
}
@@ -1,7 +1,10 @@
package com.sap.sailing.server.gateway.deserialization.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import com.sap.sailing.domain.common.impl.MeterPerSecondSpeedImpl;
@@ -12,29 +15,38 @@ import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sse.common.Util.Pair;
/**
* Make serialization on the smartphone easier by providing a flat structure rather
* than nested JSON documents.
* Make serialization on the smartphone easier by providing a flat structure rather than nested JSON documents.
*
* @author Fredrik Teschke
*
*/
public class FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer implements JsonDeserializer<Pair<UUID, GPSFixMoving>> {
public class FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer implements
JsonDeserializer<Pair<UUID, List<GPSFixMoving>>> {
public static final String DEVICE_UUID = "deviceUuid";
public static final String LON_DEG = "lonDeg";
public static final String LAT_DEG = "latDeg";
public static final String TIME_MILLIS = "timeMillis";
public static final String SPEED_M_PER_S = "speedMperS";
public static final String BEARING_DEG = "bearingDeg";
public static final String FIXES = "fixes";
public static final String LON_DEG = "longitude";
public static final String LAT_DEG = "latitude";
public static final String TIME_MILLIS = "timestamp";
public static final String SPEED_M_PER_S = "speed";
public static final String BEARING_DEG = "course";
@Override
public Pair<UUID, GPSFixMoving> deserialize(JSONObject object) throws JsonDeserializationException {
public Pair<UUID, List<GPSFixMoving>> deserialize(JSONObject object) throws JsonDeserializationException {
UUID device = UUID.fromString(object.get(DEVICE_UUID).toString());
double lonDeg = Double.parseDouble(object.get(LON_DEG).toString());
double latDeg = Double.parseDouble(object.get(LAT_DEG).toString());
long timeMillis = Long.parseLong(object.get(TIME_MILLIS).toString());
double speedMperS = Double.parseDouble(object.get(SPEED_M_PER_S).toString());
double speedKnots = new MeterPerSecondSpeedImpl(speedMperS).getKnots();
double bearingDeg = Double.parseDouble(object.get(BEARING_DEG).toString());
GPSFixMoving fix = GPSFixMovingImpl.create(lonDeg, latDeg, timeMillis, speedKnots, bearingDeg);
return new Pair<UUID, GPSFixMoving>(device, fix);
JSONArray jsonFixes = Helpers.getNestedArraySafe(object, FIXES);
List<GPSFixMoving> fixes = new ArrayList<GPSFixMoving>();
for (int i = 0; i < jsonFixes.size(); i++) {
JSONObject fixObject = Helpers.toJSONObjectSafe(jsonFixes.get(i));
double lonDeg = Double.parseDouble(fixObject.get(LON_DEG).toString());
double latDeg = Double.parseDouble(fixObject.get(LAT_DEG).toString());
long timeMillis = Long.parseLong(fixObject.get(TIME_MILLIS).toString());
double speedMperS = Double.parseDouble(fixObject.get(SPEED_M_PER_S).toString());
double speedKnots = new MeterPerSecondSpeedImpl(speedMperS).getKnots();
double bearingDeg = Double.parseDouble(fixObject.get(BEARING_DEG).toString());
GPSFixMoving fix = GPSFixMovingImpl.create(lonDeg, latDeg, timeMillis, speedKnots, bearingDeg);
fixes.add(fix);
}
return new Pair<UUID, List<GPSFixMoving>>(device, fixes);
}
}
@@ -0,0 +1,63 @@
package com.sap.sailing.server.gateway.test.jaxrs;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import java.util.UUID;
import javax.ws.rs.core.Response;
import org.json.simple.parser.ParseException;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sailing.domain.racelog.tracking.DeviceIdentifier;
import com.sap.sailing.domain.racelog.tracking.impl.SmartphoneUUIDIdentifierImpl;
import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneUuidServiceFinderFactory;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.gateway.jaxrs.api.GPSFixesResource;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
public class GPSFixesResourceTest {
private RacingEventService service;
@Before
public void setup() {
service = new RacingEventServiceImpl(true, new MockSmartphoneUuidServiceFinderFactory());
service.getMongoObjectFactory().getDatabase().dropDatabase();
}
@Test
public void deserialize() throws ParseException, TransformationException, NoCorrespondingServiceRegisteredException {
String json = "{\n" +
" \"deviceUuid\" : \"af855a56-9726-4a9c-a77e-da955bd289bf\",\n" +
" \"fixes\" : [\n" +
" {\n" +
" \"timestamp\" : 14144160080000,\n" +
" \"latitude\" : 54.325246,\n" +
" \"longitude\" : 10.148556,\n" +
" \"speed\" : 3.61,\n" +
" \"course\" : 258.11,\n" +
" },\n" +
" {\n" +
" \"timestamp\" : 14144168490000,\n" +
" \"latitude\" : 55.12456,\n" +
" \"longitude\" : 8.03456,\n" +
" \"speed\" : 5.1,\n" +
" \"course\" : 14.2,\n" +
" }\n" +
" ]\n" +
"}";
GPSFixesResource resource = new GPSFixesResource() {
public RacingEventService getService() {
return service;
};
};
Response response = resource.postFixes(json);
assertThat("response is ok", response.getStatus(), equalTo(Response.Status.OK.getStatusCode()));
DeviceIdentifier device = new SmartphoneUUIDIdentifierImpl(UUID.fromString("af855a56-9726-4a9c-a77e-da955bd289bf"));
assertThat("all fixes stored", service.getGPSFixStore().getNumberOfFixes(device), equalTo(2L));
}
}
@@ -0,0 +1,67 @@
package com.sap.sailing.server.gateway.jaxrs.api;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.ParseException;
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sailing.domain.racelog.tracking.DeviceIdentifier;
import com.sap.sailing.domain.racelog.tracking.impl.SmartphoneUUIDIdentifierImpl;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
import com.sap.sse.common.Util.Pair;
@Path("/v1/gps_fixes")
public class GPSFixesResource extends AbstractSailingServerResource {
private static final Logger logger = Logger.getLogger(GPSFixesResource.class.getName());
private final JsonDeserializer<Pair<UUID, List<GPSFixMoving>>> deserializer =
new FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer();
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response postFixes(String json) {
Pair<UUID, List<GPSFixMoving>> data = null;
try {
logger.fine("Post issued to " + this.getClass().getName());
Object requestBody = JSONValue.parseWithException(json);
JSONObject requestObject = Helpers.toJSONObjectSafe(requestBody);
logger.fine("JSON requestObject is: " + requestObject.toString());
data = deserializer.deserialize(requestObject);
} catch (ParseException | JsonDeserializationException e) {
logger.warning(String.format("Exception while parsing post request:\n%s", e.toString()));
return Response.status(Status.BAD_REQUEST).entity("Invalid JSON body in request").type(MediaType.TEXT_PLAIN).build();
}
DeviceIdentifier device = new SmartphoneUUIDIdentifierImpl(data.getA());
List<GPSFixMoving> fixes = data.getB();
try {
for (GPSFixMoving fix : fixes) {
getService().getGPSFixStore().storeFix(device, fix);
}
logger.log(Level.INFO, "Added " + fixes.size() + " fixes for device " + device.toString() + " to store");
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
logger.log(Level.WARNING, "Could not store fix for device " + device);
}
return Response.ok().build();
}
}
@@ -14,6 +14,7 @@ public class RestApiApplication extends Application {
classes.add(RegattasResource.class);
classes.add(LeaderboardsResource.class);
classes.add(SearchResource.class);
classes.add(GPSFixesResource.class);
return classes;
}
}