|
|
@@ -2,6 +2,7 @@ package cz.senslog.telemetry.server;
|
|
|
|
|
|
import cz.senslog.telemetry.app.Application;
|
|
|
import cz.senslog.telemetry.database.SortType;
|
|
|
+import cz.senslog.telemetry.database.domain.UnitLocation;
|
|
|
import cz.senslog.telemetry.database.repository.SensLogRepository;
|
|
|
import cz.senslog.telemetry.utils.TernaryCondition;
|
|
|
import io.vertx.core.http.HttpServerRequest;
|
|
|
@@ -16,15 +17,27 @@ import java.util.List;
|
|
|
import java.util.function.*;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
+import static cz.senslog.telemetry.utils.FluentInvoke.of;
|
|
|
import static java.lang.Boolean.parseBoolean;
|
|
|
import static java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME;
|
|
|
+import static java.util.Optional.ofNullable;
|
|
|
+import static java.util.stream.Collectors.groupingBy;
|
|
|
import static java.util.stream.Collectors.toList;
|
|
|
|
|
|
public class OpenAPIHandler {
|
|
|
|
|
|
+ private enum ResponseFormat {
|
|
|
+ JSON, GEOJSON
|
|
|
+ ;
|
|
|
+ public static ResponseFormat of(String format) {
|
|
|
+ return valueOf(format.toUpperCase());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private static final int DEFAULT_MAX_DATA_LIMIT = 500;
|
|
|
private static final ZoneId DEFAULT_ZONE_ID = ZoneId.of("UTC");
|
|
|
private static final boolean DEFAULT_NAVIGATION_LINKS = true;
|
|
|
+ private static final ResponseFormat DEFAULT_RESPONSE_FORMAT = ResponseFormat.JSON;
|
|
|
|
|
|
private static final BiFunction<OffsetDateTime, ZoneId, String> DATE_TIME_FORMATTER = (dateTime, zoneId) ->
|
|
|
OffsetDateTime.ofInstant(dateTime.toInstant(), zoneId).format(ISO_OFFSET_DATE_TIME);
|
|
|
@@ -164,6 +177,12 @@ public class OpenAPIHandler {
|
|
|
return Integer.parseInt(paramLimit.get(0));
|
|
|
});
|
|
|
|
|
|
+ List<String> paramFormat = rc.queryParam("format");
|
|
|
+ ResponseFormat format = TernaryCondition.<ResponseFormat>ternaryIf(paramFormat::isEmpty, DEFAULT_RESPONSE_FORMAT, () -> {
|
|
|
+ paramsJson.put("format", paramFormat.get(0));
|
|
|
+ return ResponseFormat.of(paramFormat.get(0));
|
|
|
+ });
|
|
|
+
|
|
|
List<String> paramNavigationLinks = rc.queryParam("navigationLinks");
|
|
|
boolean navigationLinks = TernaryCondition.<Boolean>ternaryIf(paramNavigationLinks::isEmpty, true, () -> {
|
|
|
paramsJson.put("navigationLinks", paramNavigationLinks.get(0));
|
|
|
@@ -183,7 +202,8 @@ public class OpenAPIHandler {
|
|
|
return String.format("%s/campaigns/%d/units/observations?offset=%d%s", host, campaignId, newOffset, (urlParams.isEmpty() ? "" : "&"+urlParams));
|
|
|
};
|
|
|
|
|
|
- repo.findObservationsByCampaignIdWithPaging(campaignId, from, to, zone, offset, limit)
|
|
|
+ switch (format) {
|
|
|
+ case JSON -> repo.findObservationsByCampaignIdWithPaging(campaignId, from, to, zone, offset, limit)
|
|
|
.onSuccess(paging -> rc.response().end(navLinks.mergeIn(navigationLinks && paging.hasNext() ? JsonObject.of(
|
|
|
"next@NavigationLink", createNextNavLink.apply(paging.size())
|
|
|
) : JsonObject.of()).mergeIn(JsonObject.of(
|
|
|
@@ -203,6 +223,34 @@ public class OpenAPIHandler {
|
|
|
"observedValues", o.getObservedValues()
|
|
|
)).collect(toList())))).encode()))
|
|
|
.onFailure(rc::fail);
|
|
|
+ case GEOJSON -> repo.findObservationsByCampaignIdWithPaging(campaignId, from, to, zone, offset, limit)
|
|
|
+ .onSuccess(paging -> rc.response().end(JsonObject.of(
|
|
|
+ "type", "FeatureCollection",
|
|
|
+ "metadata", JsonObject.of(
|
|
|
+ "size", paging.size(),
|
|
|
+ "offset", offset,
|
|
|
+ "hasNext", paging.hasNext()
|
|
|
+ ),
|
|
|
+ "features", new JsonArray(
|
|
|
+ paging.data().stream().map(o -> JsonObject.of(
|
|
|
+ "type", "Feature",
|
|
|
+ "geometry", JsonObject.of(
|
|
|
+ "type", "Point",
|
|
|
+ "coordinates", JsonArray.of(
|
|
|
+ o.getLocation().getLongitude(),
|
|
|
+ o.getLocation().getLatitude(),
|
|
|
+ o.getLocation().getAltitude()
|
|
|
+ )
|
|
|
+ ),
|
|
|
+ "properties", JsonObject.of(
|
|
|
+ "unitId", o.getUnitId(),
|
|
|
+ "timestamp", OffsetDateTime.ofInstant(o.getTimestamp().toInstant(), zone).format(ISO_OFFSET_DATE_TIME),
|
|
|
+ "speed", o.getSpeed(),
|
|
|
+ "observations", o.getObservedValues()
|
|
|
+ )
|
|
|
+ )).collect(toList()))).encode()))
|
|
|
+ .onFailure(rc::fail);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public void campaignIdUnitIdObservationsGET(RoutingContext rc) {
|
|
|
@@ -242,6 +290,12 @@ public class OpenAPIHandler {
|
|
|
return Integer.parseInt(paramLimit.get(0));
|
|
|
});
|
|
|
|
|
|
+ List<String> paramFormat = rc.queryParam("format");
|
|
|
+ ResponseFormat format = TernaryCondition.<ResponseFormat>ternaryIf(paramFormat::isEmpty, DEFAULT_RESPONSE_FORMAT, () -> {
|
|
|
+ paramsJson.put("format", paramFormat.get(0));
|
|
|
+ return ResponseFormat.of(paramFormat.get(0));
|
|
|
+ });
|
|
|
+
|
|
|
List<String> paramNavigationLinks = rc.queryParam("navigationLinks");
|
|
|
boolean navigationLinks = TernaryCondition.<Boolean>ternaryIf(paramNavigationLinks::isEmpty, true, () -> {
|
|
|
paramsJson.put("navigationLinks", paramNavigationLinks.get(0));
|
|
|
@@ -261,25 +315,56 @@ public class OpenAPIHandler {
|
|
|
return String.format("%s/campaigns/%d/units/%d/observations?offset=%d%s", host, campaignId, unitId, newOffset, (urlParams.isEmpty() ? "" : "&"+urlParams));
|
|
|
};
|
|
|
|
|
|
- repo.findObservationsByCampaignIdAndUnitIdWithPaging(campaignId, unitId, from, to, zone, offset, limit)
|
|
|
- .onSuccess(paging -> rc.response().end(navLinks.mergeIn(navigationLinks && paging.hasNext() ? JsonObject.of(
|
|
|
- "next@NavigationLink", createNextNavLink.apply(paging.size())
|
|
|
- ) : JsonObject.of()).mergeIn(JsonObject.of(
|
|
|
- "params", paramsJson,
|
|
|
- "size", paging.size(),
|
|
|
- "offset", offset,
|
|
|
- "hasNext", paging.hasNext(),
|
|
|
- "data", new JsonArray(
|
|
|
- paging.data().stream().map(o -> JsonObject.of(
|
|
|
- "timestamp", OffsetDateTime.ofInstant(o.getTimestamp().toInstant(), zone).format(ISO_OFFSET_DATE_TIME),
|
|
|
- "speed", o.getSpeed(),
|
|
|
- "location", JsonObject.of(
|
|
|
- "longitude", o.getLocation().getLongitude(),
|
|
|
- "latitude", o.getLocation().getLatitude(),
|
|
|
- "altitude", o.getLocation().getAltitude()),
|
|
|
- "observedValues", o.getObservedValues()
|
|
|
- )).collect(toList())))).encode()))
|
|
|
- .onFailure(rc::fail);
|
|
|
+ switch (format) {
|
|
|
+ case JSON ->
|
|
|
+ repo.findObservationsByCampaignIdAndUnitIdWithPaging(campaignId, unitId, from, to, zone, offset, limit)
|
|
|
+ .onSuccess(paging -> rc.response().end(navLinks.mergeIn(navigationLinks && paging.hasNext() ? JsonObject.of(
|
|
|
+ "next@NavigationLink", createNextNavLink.apply(paging.size())
|
|
|
+ ) : JsonObject.of()).mergeIn(JsonObject.of(
|
|
|
+ "params", paramsJson,
|
|
|
+ "size", paging.size(),
|
|
|
+ "offset", offset,
|
|
|
+ "hasNext", paging.hasNext(),
|
|
|
+ "data", new JsonArray(
|
|
|
+ paging.data().stream().map(o -> JsonObject.of(
|
|
|
+ "timestamp", OffsetDateTime.ofInstant(o.getTimestamp().toInstant(), zone).format(ISO_OFFSET_DATE_TIME),
|
|
|
+ "speed", o.getSpeed(),
|
|
|
+ "location", JsonObject.of(
|
|
|
+ "longitude", o.getLocation().getLongitude(),
|
|
|
+ "latitude", o.getLocation().getLatitude(),
|
|
|
+ "altitude", o.getLocation().getAltitude()),
|
|
|
+ "observedValues", o.getObservedValues()
|
|
|
+ )).collect(toList())))).encode()))
|
|
|
+ .onFailure(rc::fail);
|
|
|
+ case GEOJSON ->
|
|
|
+ repo.findObservationsByCampaignIdAndUnitIdWithPaging(campaignId, unitId, from, to, zone, offset, limit)
|
|
|
+ .onSuccess(paging -> rc.response().end(JsonObject.of(
|
|
|
+ "type", "FeatureCollection",
|
|
|
+ "metadata", JsonObject.of(
|
|
|
+ "size", paging.size(),
|
|
|
+ "offset", offset,
|
|
|
+ "hasNext", paging.hasNext()
|
|
|
+ ),
|
|
|
+ "features", new JsonArray(
|
|
|
+ paging.data().stream().map(o -> JsonObject.of(
|
|
|
+ "type", "Feature",
|
|
|
+ "geometry", JsonObject.of(
|
|
|
+ "type", "Point",
|
|
|
+ "coordinates", JsonArray.of(
|
|
|
+ o.getLocation().getLongitude(),
|
|
|
+ o.getLocation().getLatitude(),
|
|
|
+ o.getLocation().getAltitude()
|
|
|
+ )
|
|
|
+ ),
|
|
|
+ "properties", JsonObject.of(
|
|
|
+ "unitId", o.getUnitId(),
|
|
|
+ "timestamp", OffsetDateTime.ofInstant(o.getTimestamp().toInstant(), zone).format(ISO_OFFSET_DATE_TIME),
|
|
|
+ "speed", o.getSpeed(),
|
|
|
+ "observations", o.getObservedValues()
|
|
|
+ )
|
|
|
+ )).collect(toList()))).encode()))
|
|
|
+ .onFailure(rc::fail);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public void campaignIdUnitsObservationsLocationsGET(RoutingContext rc) {
|
|
|
@@ -317,6 +402,12 @@ public class OpenAPIHandler {
|
|
|
return ZoneId.of(paramZone.get(0));
|
|
|
});
|
|
|
|
|
|
+ List<String> paramFormat = rc.queryParam("format");
|
|
|
+ ResponseFormat format = TernaryCondition.<ResponseFormat>ternaryIf(paramFormat::isEmpty, DEFAULT_RESPONSE_FORMAT, () -> {
|
|
|
+ paramsJson.put("format", paramFormat.get(0));
|
|
|
+ return ResponseFormat.of(paramFormat.get(0));
|
|
|
+ });
|
|
|
+
|
|
|
List<String> paramNavigationLinks = rc.queryParam("navigationLinks");
|
|
|
boolean navigationLinks = TernaryCondition.<Boolean>ternaryIf(paramNavigationLinks::isEmpty, true, () -> {
|
|
|
paramsJson.put("navigationLinks", paramNavigationLinks.get(0));
|
|
|
@@ -327,20 +418,43 @@ public class OpenAPIHandler {
|
|
|
"Campaign@NavigationLink", String.format("%s/campaigns/%d",host, campaignId)
|
|
|
) : JsonObject.of();
|
|
|
|
|
|
- repo.findUnitsLocationsByCampaignId(campaignId, limitPerUnit, from, to, zone, sortType)
|
|
|
- .onSuccess(locations -> rc.response().end(navLinks.mergeIn(JsonObject.of(
|
|
|
- "params", paramsJson,
|
|
|
- "size", locations.size(),
|
|
|
- "data", new JsonArray(locations.stream().map(l -> JsonObject.of(
|
|
|
- "unitId", l.getUnitId(),
|
|
|
- "timestamp", OffsetDateTime.ofInstant(l.getTimestamp().toInstant(), zone).format(ISO_OFFSET_DATE_TIME),
|
|
|
- "location", JsonArray.of(
|
|
|
- l.getLocation().getLongitude(),
|
|
|
- l.getLocation().getLatitude(),
|
|
|
- l.getLocation().getAltitude()
|
|
|
- )
|
|
|
- )).collect(toList())))).encode()))
|
|
|
- .onFailure(rc::fail);
|
|
|
+ switch (format) {
|
|
|
+ case JSON -> repo.findUnitsLocationsByCampaignId(campaignId, limitPerUnit, from, to, zone, sortType)
|
|
|
+ .onSuccess(locations -> rc.response().end(navLinks.mergeIn(JsonObject.of(
|
|
|
+ "params", paramsJson,
|
|
|
+ "size", locations.size(),
|
|
|
+ "data", new JsonArray(locations.stream().map(l -> JsonObject.of(
|
|
|
+ "unitId", l.getUnitId(),
|
|
|
+ "timestamp", OffsetDateTime.ofInstant(l.getTimestamp().toInstant(), zone).format(ISO_OFFSET_DATE_TIME),
|
|
|
+ "location", JsonArray.of(
|
|
|
+ l.getLocation().getLongitude(),
|
|
|
+ l.getLocation().getLatitude(),
|
|
|
+ l.getLocation().getAltitude()
|
|
|
+ )
|
|
|
+ )).collect(toList())))).encode()))
|
|
|
+ .onFailure(rc::fail);
|
|
|
+ case GEOJSON -> repo.findUnitsLocationsByCampaignId(campaignId, limitPerUnit, from, to, zone, sortType)
|
|
|
+ .onSuccess(data -> of(data.stream().collect(groupingBy(UnitLocation::getUnitId))).then(unitLocation -> rc.response().end(JsonObject.of(
|
|
|
+ "type", "FeatureCollection",
|
|
|
+ "metadata", JsonObject.of(
|
|
|
+ "limitPerUnit", limitPerUnit
|
|
|
+ ),
|
|
|
+ "features", unitLocation.entrySet().stream().map(entry -> JsonObject.of(
|
|
|
+ "type", "Feature",
|
|
|
+ "geometry", JsonObject.of(
|
|
|
+ "type", "MultiPoint",
|
|
|
+ "properties", JsonObject.of(
|
|
|
+ "unitId", entry.getKey()
|
|
|
+ ),
|
|
|
+ "coordinates", new JsonArray(entry.getValue().stream().map(l -> JsonArray.of(
|
|
|
+ l.getLocation().getLongitude(),
|
|
|
+ l.getLocation().getLatitude(),
|
|
|
+ l.getLocation().getAltitude()
|
|
|
+ )).collect(toList()))
|
|
|
+ )
|
|
|
+ )).collect(toList())).encode())))
|
|
|
+ .onFailure(rc::fail);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public void campaignIdUnitIdLocationsGET(RoutingContext rc) {
|
|
|
@@ -380,7 +494,18 @@ public class OpenAPIHandler {
|
|
|
return Integer.parseInt(paramLimit.get(0));
|
|
|
});
|
|
|
|
|
|
+ List<String> paramFormat = rc.queryParam("format");
|
|
|
+ ResponseFormat format = TernaryCondition.<ResponseFormat>ternaryIf(paramFormat::isEmpty, DEFAULT_RESPONSE_FORMAT, () -> {
|
|
|
+ paramsJson.put("format", paramFormat.get(0));
|
|
|
+ return ResponseFormat.of(paramFormat.get(0));
|
|
|
+ });
|
|
|
+
|
|
|
List<String> filter = rc.queryParam("filter");
|
|
|
+ // TODO implement filter
|
|
|
+ /*
|
|
|
+ filtr=sensorId(10003)gt10
|
|
|
+ filtr=driverId(34245)eq3
|
|
|
+ */
|
|
|
|
|
|
List<String> paramNavigationLinks = rc.queryParam("navigationLinks");
|
|
|
boolean navigationLinks = TernaryCondition.<Boolean>ternaryIf(paramNavigationLinks::isEmpty, true, () -> {
|
|
|
@@ -402,8 +527,8 @@ public class OpenAPIHandler {
|
|
|
return String.format("%s/campaigns/%d/units/%d/observations/locations?offset=%d&%s", host, campaignId, unitId, newOffset, urlParams);
|
|
|
};
|
|
|
|
|
|
- if (filter.isEmpty()) {
|
|
|
- repo.findLocationsByCampaignIdAndUnitIdWithPaging(campaignId, unitId, from, to, zone, offset, limit)
|
|
|
+ switch (format) {
|
|
|
+ case JSON -> repo.findLocationsByCampaignIdAndUnitIdWithPaging(campaignId, unitId, from, to, zone, offset, limit)
|
|
|
.onSuccess(paging -> rc.response().end(navLinks.mergeIn(navigationLinks && paging.hasNext() ? JsonObject.of(
|
|
|
"next@NavigationLink", createNextNavLink.apply(paging.size())
|
|
|
) : JsonObject.of()).mergeIn(JsonObject.of(
|
|
|
@@ -421,12 +546,26 @@ public class OpenAPIHandler {
|
|
|
)
|
|
|
)).collect(toList())))).encode()))
|
|
|
.onFailure(rc::fail);
|
|
|
- } else {
|
|
|
- // TODO implement filter
|
|
|
- /*
|
|
|
- filtr=sensorId(10003)gt10
|
|
|
- filtr=driverId(34245)eq3
|
|
|
- */
|
|
|
+ case GEOJSON -> repo.findLocationsByCampaignIdAndUnitIdWithPaging(campaignId, unitId, from, to, zone, offset, limit)
|
|
|
+ .onSuccess(paging -> rc.response().end(JsonObject.of(
|
|
|
+ "type", "Feature",
|
|
|
+ "metadata", JsonObject.of(
|
|
|
+ "size", paging.size(),
|
|
|
+ "offset", offset,
|
|
|
+ "hasNext", paging.hasNext()
|
|
|
+ ),
|
|
|
+ "properties", JsonObject.of(
|
|
|
+ "unitId", unitId
|
|
|
+ ),
|
|
|
+ "geometry", JsonObject.of(
|
|
|
+ "type", "MultiPoint",
|
|
|
+ "coordinates", new JsonArray(paging.data().stream().map(l -> JsonArray.of(
|
|
|
+ l.getLocation().getLongitude(),
|
|
|
+ l.getLocation().getLatitude(),
|
|
|
+ l.getLocation().getAltitude()
|
|
|
+ )).collect(toList())))
|
|
|
+ ).encode()))
|
|
|
+ .onFailure(rc::fail);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -753,6 +892,12 @@ public class OpenAPIHandler {
|
|
|
return Integer.parseInt(paramLimit.get(0));
|
|
|
});
|
|
|
|
|
|
+ List<String> paramFormat = rc.queryParam("format");
|
|
|
+ ResponseFormat format = TernaryCondition.<ResponseFormat>ternaryIf(paramFormat::isEmpty, DEFAULT_RESPONSE_FORMAT, () -> {
|
|
|
+ paramsJson.put("format", paramFormat.get(0));
|
|
|
+ return ResponseFormat.of(paramFormat.get(0));
|
|
|
+ });
|
|
|
+
|
|
|
List<String> paramNavigationLinks = rc.queryParam("navigationLinks");
|
|
|
boolean navigationLinks = TernaryCondition.<Boolean>ternaryIf(paramNavigationLinks::isEmpty, true, () -> {
|
|
|
paramsJson.put("navigationLinks", paramNavigationLinks.get(0));
|
|
|
@@ -772,25 +917,56 @@ public class OpenAPIHandler {
|
|
|
return String.format("%s/campaigns/%d/units/%d/sensors/%d/observations?offset=%d%s", host, campaignId, unitId, sensorId, newOffset, (urlParams.isEmpty() ? "" : "&"+urlParams));
|
|
|
};
|
|
|
|
|
|
- repo.findObservationsByCampaignIdAndUnitIdAndSensorIdWithPaging(campaignId, unitId, sensorId, from, to, zone, offset, limit)
|
|
|
- .onSuccess(paging -> rc.response().end(navLinks.mergeIn(navigationLinks && paging.hasNext() ? JsonObject.of(
|
|
|
- "next@NavigationLink", createNextNavLink.apply(paging.size())
|
|
|
- ) : JsonObject.of()).mergeIn(JsonObject.of(
|
|
|
- "params", paramsJson,
|
|
|
- "size", paging.size(),
|
|
|
- "offset", offset,
|
|
|
- "hasNext", paging.hasNext(),
|
|
|
- "data", new JsonArray(
|
|
|
- paging.data().stream().map(o -> JsonObject.of(
|
|
|
- "value", o.getValue(),
|
|
|
- "timestamp", OffsetDateTime.ofInstant(o.getTimestamp().toInstant(), zone).format(ISO_OFFSET_DATE_TIME),
|
|
|
- "speed", o.getSpeed(),
|
|
|
- "location", JsonObject.of(
|
|
|
- "longitude", o.getLocation().getLongitude(),
|
|
|
- "latitude", o.getLocation().getLatitude(),
|
|
|
- "altitude", o.getLocation().getAltitude())
|
|
|
- )).collect(toList())))).encode()))
|
|
|
- .onFailure(rc::fail);
|
|
|
+ switch (format) {
|
|
|
+ case JSON -> repo.findObservationsByCampaignIdAndUnitIdAndSensorIdWithPaging(campaignId, unitId, sensorId, from, to, zone, offset, limit)
|
|
|
+ .onSuccess(paging -> rc.response().end(navLinks.mergeIn(navigationLinks && paging.hasNext() ? JsonObject.of(
|
|
|
+ "next@NavigationLink", createNextNavLink.apply(paging.size())
|
|
|
+ ) : JsonObject.of()).mergeIn(JsonObject.of(
|
|
|
+ "params", paramsJson,
|
|
|
+ "size", paging.size(),
|
|
|
+ "offset", offset,
|
|
|
+ "hasNext", paging.hasNext(),
|
|
|
+ "data", new JsonArray(
|
|
|
+ paging.data().stream().map(o -> JsonObject.of(
|
|
|
+ "value", o.getValue(),
|
|
|
+ "timestamp", OffsetDateTime.ofInstant(o.getTimestamp().toInstant(), zone).format(ISO_OFFSET_DATE_TIME),
|
|
|
+ "speed", o.getSpeed(),
|
|
|
+ "location", JsonObject.of(
|
|
|
+ "longitude", o.getLocation().getLongitude(),
|
|
|
+ "latitude", o.getLocation().getLatitude(),
|
|
|
+ "altitude", o.getLocation().getAltitude())
|
|
|
+ )).collect(toList())))).encode()))
|
|
|
+ .onFailure(rc::fail);
|
|
|
+ case GEOJSON -> repo.findObservationsByCampaignIdAndUnitIdAndSensorIdWithPaging(campaignId, unitId, sensorId, from, to, zone, offset, limit)
|
|
|
+ .onSuccess(paging -> rc.response().end(JsonObject.of(
|
|
|
+ "type", "FeatureCollection",
|
|
|
+ "metadata", JsonObject.of(
|
|
|
+ "size", paging.size(),
|
|
|
+ "offset", offset,
|
|
|
+ "hasNext", paging.hasNext()
|
|
|
+ ),
|
|
|
+ "features", new JsonArray(
|
|
|
+ paging.data().stream().map(o -> JsonObject.of(
|
|
|
+ "type", "Feature",
|
|
|
+ "geometry", JsonObject.of(
|
|
|
+ "type", "Point",
|
|
|
+ "coordinates", JsonArray.of(
|
|
|
+ o.getLocation().getLongitude(),
|
|
|
+ o.getLocation().getLatitude(),
|
|
|
+ o.getLocation().getAltitude()
|
|
|
+ )
|
|
|
+ ),
|
|
|
+ "properties", JsonObject.of(
|
|
|
+ "unitId", unitId,
|
|
|
+ "timestamp", OffsetDateTime.ofInstant(o.getTimestamp().toInstant(), zone).format(ISO_OFFSET_DATE_TIME),
|
|
|
+ "speed", o.getSpeed(),
|
|
|
+ "observations", JsonObject.of(
|
|
|
+ String.valueOf(sensorId), o.getValue()
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )).collect(toList()))).encode()))
|
|
|
+ .onFailure(rc::fail);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public void driversGET(RoutingContext rc) {
|
|
|
@@ -975,7 +1151,7 @@ public class OpenAPIHandler {
|
|
|
"self@NavigationLink", String.format("%s/drivers/%d/actions/%d/units/%d", host, driverId, actionId, u.getUnitId()),
|
|
|
"Unit@NavigationLink", String.format("%s/units/%d", host, u.getUnitId()),
|
|
|
"DriverAction@NavigationLink", String.format("%s/drivers/%d/actions/%d", host, driverId, actionId),
|
|
|
- "Events@NavigationLink", String.format("%s/ drivers/%d/units/%d/actions/%d/events", host, driverId, u.getUnitId(), actionId)
|
|
|
+ "Events@NavigationLink", String.format("%s/drivers/%d/units/%d/actions/%d/events", host, driverId, u.getUnitId(), actionId)
|
|
|
) : JsonObject.of()).mergeIn(JsonObject.of(
|
|
|
"unitId", u.getUnitId(),
|
|
|
"name", u.getName(),
|
|
|
@@ -1099,6 +1275,12 @@ public class OpenAPIHandler {
|
|
|
return Integer.parseInt(paramLimit.get(0));
|
|
|
});
|
|
|
|
|
|
+ List<String> paramFormat = rc.queryParam("format");
|
|
|
+ ResponseFormat format = TernaryCondition.<ResponseFormat>ternaryIf(paramFormat::isEmpty, DEFAULT_RESPONSE_FORMAT, () -> {
|
|
|
+ paramsJson.put("format", paramFormat.get(0));
|
|
|
+ return ResponseFormat.of(paramFormat.get(0));
|
|
|
+ });
|
|
|
+
|
|
|
List<String> paramNavigationLinks = rc.queryParam("navigationLinks");
|
|
|
boolean navigationLinks = TernaryCondition.<Boolean>ternaryIf(paramNavigationLinks::isEmpty, true, () -> {
|
|
|
paramsJson.put("navigationLinks", paramNavigationLinks.get(0));
|
|
|
@@ -1118,25 +1300,54 @@ public class OpenAPIHandler {
|
|
|
return String.format("%s/events/%d/observations?offset=%d%s", host, eventId, newOffset, (urlParams.isEmpty() ? "" : "&"+urlParams));
|
|
|
};
|
|
|
|
|
|
- repo.findObservationsByEventIdWithPaging(eventId, from, to, zone, offset, limit)
|
|
|
- .onSuccess(paging -> rc.response().end(navLinks.mergeIn(navigationLinks && paging.hasNext() ? JsonObject.of(
|
|
|
- "next@NavigationLink", createNextNavLink.apply(paging.size())
|
|
|
- ) : JsonObject.of()).mergeIn(JsonObject.of(
|
|
|
- "params", paramsJson,
|
|
|
- "size", paging.size(),
|
|
|
- "offset", offset,
|
|
|
- "hasNext", paging.hasNext(),
|
|
|
- "data", new JsonArray(
|
|
|
- paging.data().stream().map(o -> JsonObject.of(
|
|
|
- "timestamp", OffsetDateTime.ofInstant(o.getTimestamp().toInstant(), zone).format(ISO_OFFSET_DATE_TIME),
|
|
|
- "speed", o.getSpeed(),
|
|
|
- "location", JsonObject.of(
|
|
|
- "longitude", o.getLocation().getLongitude(),
|
|
|
- "latitude", o.getLocation().getLatitude(),
|
|
|
- "altitude", o.getLocation().getAltitude()),
|
|
|
- "observedValues", o.getObservedValues()
|
|
|
- )).collect(toList())))).encode()))
|
|
|
- .onFailure(rc::fail);
|
|
|
+ switch (format) {
|
|
|
+ case JSON -> repo.findObservationsByEventIdWithPaging(eventId, from, to, zone, offset, limit)
|
|
|
+ .onSuccess(paging -> rc.response().end(navLinks.mergeIn(navigationLinks && paging.hasNext() ? JsonObject.of(
|
|
|
+ "next@NavigationLink", createNextNavLink.apply(paging.size())
|
|
|
+ ) : JsonObject.of()).mergeIn(JsonObject.of(
|
|
|
+ "params", paramsJson,
|
|
|
+ "size", paging.size(),
|
|
|
+ "offset", offset,
|
|
|
+ "hasNext", paging.hasNext(),
|
|
|
+ "data", new JsonArray(
|
|
|
+ paging.data().stream().map(o -> JsonObject.of(
|
|
|
+ "timestamp", OffsetDateTime.ofInstant(o.getTimestamp().toInstant(), zone).format(ISO_OFFSET_DATE_TIME),
|
|
|
+ "speed", o.getSpeed(),
|
|
|
+ "location", JsonObject.of(
|
|
|
+ "longitude", o.getLocation().getLongitude(),
|
|
|
+ "latitude", o.getLocation().getLatitude(),
|
|
|
+ "altitude", o.getLocation().getAltitude()),
|
|
|
+ "observedValues", o.getObservedValues()
|
|
|
+ )).collect(toList())))).encode()))
|
|
|
+ .onFailure(rc::fail);
|
|
|
+ case GEOJSON -> repo.findObservationsByEventIdWithPaging(eventId, from, to, zone, offset, limit)
|
|
|
+ .onSuccess(paging -> rc.response().end(JsonObject.of(
|
|
|
+ "type", "FeatureCollection",
|
|
|
+ "metadata", JsonObject.of(
|
|
|
+ "size", paging.size(),
|
|
|
+ "offset", offset,
|
|
|
+ "hasNext", paging.hasNext()
|
|
|
+ ),
|
|
|
+ "features", new JsonArray(
|
|
|
+ paging.data().stream().map(o -> JsonObject.of(
|
|
|
+ "type", "Feature",
|
|
|
+ "geometry", JsonObject.of(
|
|
|
+ "type", "Point",
|
|
|
+ "coordinates", JsonArray.of(
|
|
|
+ o.getLocation().getLongitude(),
|
|
|
+ o.getLocation().getLatitude(),
|
|
|
+ o.getLocation().getAltitude()
|
|
|
+ )
|
|
|
+ ),
|
|
|
+ "properties", JsonObject.of(
|
|
|
+ "unitId", o.getUnitId(),
|
|
|
+ "timestamp", OffsetDateTime.ofInstant(o.getTimestamp().toInstant(), zone).format(ISO_OFFSET_DATE_TIME),
|
|
|
+ "speed", o.getSpeed(),
|
|
|
+ "observations", o.getObservedValues()
|
|
|
+ )
|
|
|
+ )).collect(toList()))).encode()))
|
|
|
+ .onFailure(rc::fail);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public void eventIdLocationsGET(RoutingContext rc) {
|
|
|
@@ -1175,6 +1386,12 @@ public class OpenAPIHandler {
|
|
|
return Integer.parseInt(paramLimit.get(0));
|
|
|
});
|
|
|
|
|
|
+ List<String> paramFormat = rc.queryParam("format");
|
|
|
+ ResponseFormat format = TernaryCondition.<ResponseFormat>ternaryIf(paramFormat::isEmpty, DEFAULT_RESPONSE_FORMAT, () -> {
|
|
|
+ paramsJson.put("format", paramFormat.get(0));
|
|
|
+ return ResponseFormat.of(paramFormat.get(0));
|
|
|
+ });
|
|
|
+
|
|
|
List<String> paramNavigationLinks = rc.queryParam("navigationLinks");
|
|
|
boolean navigationLinks = TernaryCondition.<Boolean>ternaryIf(paramNavigationLinks::isEmpty, true, () -> {
|
|
|
paramsJson.put("navigationLinks", paramNavigationLinks.get(0));
|
|
|
@@ -1194,24 +1411,45 @@ public class OpenAPIHandler {
|
|
|
return String.format("%s/events/%d/observations/locations?offset=%d%s", host, eventId, newOffset, (urlParams.isEmpty() ? "" : "&"+urlParams));
|
|
|
};
|
|
|
|
|
|
- repo.findLocationsByEventIdWithPaging(eventId, from, to, zone, offset, limit)
|
|
|
- .onSuccess(paging -> rc.response().end(navLinks.mergeIn(navigationLinks && paging.hasNext() ? JsonObject.of(
|
|
|
- "next@NavigationLink", createNextNavLink.apply(paging.size())
|
|
|
- ) : JsonObject.of()).mergeIn(JsonObject.of(
|
|
|
- "params", paramsJson,
|
|
|
- "size", paging.size(),
|
|
|
- "offset", offset,
|
|
|
- "hasNext", paging.hasNext(),
|
|
|
- "data", new JsonArray(
|
|
|
- paging.data().stream().map(l -> JsonObject.of(
|
|
|
- "timestamp", OffsetDateTime.ofInstant(l.getTimestamp().toInstant(), zone).format(ISO_OFFSET_DATE_TIME),
|
|
|
- "location", JsonArray.of(
|
|
|
- l.getLocation().getLongitude(),
|
|
|
- l.getLocation().getLatitude(),
|
|
|
- l.getLocation().getAltitude()
|
|
|
- )
|
|
|
- )).collect(toList())))).encode()))
|
|
|
- .onFailure(rc::fail);
|
|
|
+ switch (format) {
|
|
|
+ case JSON -> repo.findLocationsByEventIdWithPaging(eventId, from, to, zone, offset, limit)
|
|
|
+ .onSuccess(paging -> rc.response().end(navLinks.mergeIn(navigationLinks && paging.hasNext() ? JsonObject.of(
|
|
|
+ "next@NavigationLink", createNextNavLink.apply(paging.size())
|
|
|
+ ) : JsonObject.of()).mergeIn(JsonObject.of(
|
|
|
+ "params", paramsJson,
|
|
|
+ "size", paging.size(),
|
|
|
+ "offset", offset,
|
|
|
+ "hasNext", paging.hasNext(),
|
|
|
+ "data", new JsonArray(
|
|
|
+ paging.data().stream().map(l -> JsonObject.of(
|
|
|
+ "timestamp", OffsetDateTime.ofInstant(l.getTimestamp().toInstant(), zone).format(ISO_OFFSET_DATE_TIME),
|
|
|
+ "location", JsonArray.of(
|
|
|
+ l.getLocation().getLongitude(),
|
|
|
+ l.getLocation().getLatitude(),
|
|
|
+ l.getLocation().getAltitude()
|
|
|
+ )
|
|
|
+ )).collect(toList())))).encode()))
|
|
|
+ .onFailure(rc::fail);
|
|
|
+ case GEOJSON -> repo.findLocationsByEventIdWithPaging(eventId, from, to, zone, offset, limit)
|
|
|
+ .onSuccess(paging -> rc.response().end(JsonObject.of(
|
|
|
+ "type", "Feature",
|
|
|
+ "metadata", JsonObject.of(
|
|
|
+ "size", paging.size(),
|
|
|
+ "offset", offset,
|
|
|
+ "hasNext", paging.hasNext()
|
|
|
+ ),
|
|
|
+ "properties", ofNullable(paging.size() > 0 ? paging.data().get(0) : null)
|
|
|
+ .map(l -> JsonObject.of("unitId", l.getUnitId())).orElseGet(JsonObject::new),
|
|
|
+ "geometry", JsonObject.of(
|
|
|
+ "type", "MultiPoint",
|
|
|
+ "coordinates", new JsonArray(paging.data().stream().map(l -> JsonArray.of(
|
|
|
+ l.getLocation().getLongitude(),
|
|
|
+ l.getLocation().getLatitude(),
|
|
|
+ l.getLocation().getAltitude()
|
|
|
+ )).collect(toList())))
|
|
|
+ ).encode()))
|
|
|
+ .onFailure(rc::fail);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public void unitIdDriversGET(RoutingContext rc) {
|