package ru.semiot.services.tsdbservice.rest;
import static ru.semiot.services.tsdbservice.rest.ResponseModelOrError.responseModelOrError;
import static ru.semiot.services.tsdbservice.rest.ResponseStringOrError.responseStringOrError;
import com.datastax.driver.core.ResultSet;
import org.apache.commons.lang3.StringUtils;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.semiot.services.tsdbservice.TSDBClient;
import ru.semiot.services.tsdbservice.model.Observation;
import rx.Observable;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.container.Suspended;
import javax.ws.rs.core.Response;
@Path("/observations")
public class Observations {
private static final Logger logger = LoggerFactory
.getLogger(Observations.class);
public static final String GET_LATEST_OBSERVATION = "SELECT * FROM semiot.observation "
+ "WHERE system_id = '${SYSTEM_ID}' AND sensor_id IN (${SENSOR_IDS}) LIMIT 1";
public static final String GET_OBSERVATIONS_BY_START_END =
"SELECT * FROM semiot.observation WHERE "
+ "event_time >= '${START}' AND event_time <= '${END}' "
+ "AND system_id = '${SYSTEM_ID}' AND sensor_id IN (${SENSOR_IDS});";
public static final String GET_OBSERVATIONS_BY_START = "SELECT * FROM semiot.observation WHERE "
+ "event_time >= '${START}' AND system_id = '${SYSTEM_ID}' AND sensor_id IN (${SENSOR_IDS});";
public static final String SENSOR_ID = "'${SENSOR_ID}'";
@GET
@Path("test")
public String test() {
return "Test";
}
@GET
public void getObservationsByRange(@Suspended final AsyncResponse response,
@QueryParam("system_id") String systemId, @QueryParam("sensor_id") List<String> listSensorId,
@QueryParam("start") String start, @QueryParam("end") String end) {
if (StringUtils.isEmpty(systemId) || listSensorId.isEmpty() || StringUtils.isEmpty(start)) {
response.resume(Response.status(Response.Status.BAD_REQUEST).build());
} else {
Observable<ResultSet> rs;
String getObservations;
if (StringUtils.isNoneEmpty(end)) {
getObservations = GET_OBSERVATIONS_BY_START_END
.replace("${SYSTEM_ID}", systemId)
.replace("${START}", start).replace("${END}", end);
} else {
getObservations = GET_OBSERVATIONS_BY_START
.replace("${SYSTEM_ID}", systemId)
.replace("${START}", start);
}
rs = TSDBClient.getInstance().executeAsync(getObservations
.replace("${SYSTEM_ID}", systemId)
.replace("${SENSOR_IDS}", toSensors(listSensorId)));
resultSetToRfd(response, rs);
}
}
@GET
@Path("/latest")
public void getObservationsLatest(@Suspended final AsyncResponse response,
@QueryParam("system_id") String systemId,
@QueryParam("sensor_id") List<String> listSensorId) {
if (StringUtils.isEmpty(systemId) || listSensorId.isEmpty()) {
response.resume(Response.status(Response.Status.BAD_REQUEST).build());
} else {
Observable<ResultSet> rs = TSDBClient.getInstance().executeAsync(GET_LATEST_OBSERVATION
.replace("${SYSTEM_ID}", systemId)
.replace("${SENSOR_IDS}", toSensors(listSensorId)));
resultSetToRfd(response, rs);
}
}
@GET
@Path("/latest/time")
public void getTimeObservationsLatest(@Suspended final AsyncResponse response,
@QueryParam("system_id") String systemId,
@QueryParam("sensor_id") List<String> listSensorId) {
if (StringUtils.isEmpty(systemId) || listSensorId.isEmpty()) {
response.resume(Response.status(Response.Status.BAD_REQUEST).build());
} else {
Observable<ResultSet> rs = TSDBClient.getInstance().executeAsync(GET_LATEST_OBSERVATION
.replace("${SYSTEM_ID}", systemId)
.replace("${SENSOR_IDS}", toSensors(listSensorId)));
rs.map((result) -> {
if(!result.isExhausted()) {
return result.one().getTimestamp("event_time").toInstant().toString();
} else {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
}).subscribe(responseStringOrError(response));
}
}
private String toSensors(List<String> listSensorId) {
StringBuilder partitionKeys = new StringBuilder();
boolean isFirst = true;
for (String sensorId : listSensorId) {
if (isFirst) {
isFirst = false;
} else {
partitionKeys.append(", ");
}
partitionKeys.append(SENSOR_ID.replace("${SENSOR_ID}", sensorId));
}
return partitionKeys.toString();
}
private void resultSetToRfd(final AsyncResponse response,
Observable<ResultSet> rs) {
rs.map((result) -> {
Model observations = ModelFactory.createDefaultModel();
result.forEach((row) -> {
Observation observation = new Observation(
row.getString("system_id"), row.getString("sensor_id"),
row.getTimestamp("event_time").toInstant().toString(),
row.getString("property"),
row.getString("feature_of_interest"),
row.getString("value"));
observations.add(observation.toRDF());
});
return observations;
}).subscribe(responseModelOrError(response));
}
}