package ru.semiot.platform.apigateway.rest;
import static ru.semiot.commons.restapi.AsyncResponseHelper.resumeOnError;
import com.github.jsonldjava.utils.JsonUtils;
import org.aeonbits.owner.ConfigFactory;
import org.apache.jena.ext.com.google.common.base.Strings;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ResIterator;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.vocabulary.RDF;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.semiot.commons.namespaces.Hydra;
import ru.semiot.commons.namespaces.SEMIOT;
import ru.semiot.commons.rdf.ModelJsonLdUtils;
import ru.semiot.commons.restapi.MediaType;
import ru.semiot.platform.apigateway.ServerConfig;
import ru.semiot.platform.apigateway.beans.TSDBQueryService;
import ru.semiot.platform.apigateway.beans.impl.ContextProvider;
import ru.semiot.platform.apigateway.beans.impl.DeviceProxyService;
import ru.semiot.platform.apigateway.utils.MapBuilder;
import ru.semiot.platform.apigateway.utils.RDFUtils;
import ru.semiot.platform.apigateway.utils.URIUtils;
import java.net.URI;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.container.Suspended;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
@Path("/systems/{system_id}/commandResults")
@Stateless
public class SystemCommandResultsResource {
private static final Logger logger = LoggerFactory.getLogger(SystemCommandResultsResource.class);
private static final ServerConfig config = ConfigFactory.create(ServerConfig.class);
public SystemCommandResultsResource() {
super();
}
@Inject
ContextProvider contextProvider;
@Inject
TSDBQueryService tsdb;
@Inject
DeviceProxyService dps;
@Context
UriInfo uriInfo;
@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_LD_JSON})
public void getCommandResults(@Suspended AsyncResponse response,
@PathParam("system_id") String systemId, @QueryParam("start") ZonedDateTime start,
@QueryParam("end") ZonedDateTime end) {
URI root = uriInfo.getRequestUri();
String rootURL = URIUtils.extractRootURL(root);
Map params = MapBuilder.newMap()
.put(ContextProvider.VAR_ROOT_URL, rootURL)
.put(ContextProvider.VAR_WAMP_URL, UriBuilder
.fromUri(rootURL + config.wampPublicPath())
.scheme(config.wampProtocolScheme()).build())
.put(ContextProvider.VAR_SYSTEM_ID, systemId)
.build();
if (Strings.isNullOrEmpty(systemId)) {
response.resume(Response.status(Response.Status.NOT_FOUND).build());
}
if (start == null) {
tsdb.queryDateTimeOfLatestCommandResult(systemId, null).subscribe((dateTime) -> {
if (dateTime != null) {
response.resume(Response.seeOther(
UriBuilder.fromUri(root)
.queryParam("start", dateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME))
.build())
.build());
} else {
try {
Map<String, Object> frame = contextProvider.getFrame(
ContextProvider.SYSTEM_COMMANDRESULTS_COLLECTION, rootURL);
params.put(ContextProvider.VAR_QUERY_PARAMS, "?noparams");
Model model = contextProvider.getRDFModel(
ContextProvider.SYSTEM_COMMANDRESULTS_COLLECTION, params);
Resource view = RDFUtils.subjectWithProperty(
model, RDF.type, Hydra.PartialCollectionView);
model.removeAll(view, null, null);
response.resume(JsonUtils.toPrettyString(
ModelJsonLdUtils.toJsonLdCompact(model, frame)));
} catch (Throwable ex) {
resumeOnError(response, ex);
}
}
}, resumeOnError(response));
} else {
String queryParams = "?start=" + start;
if (end != null) {
queryParams += "&end=" + end;
}
params.put(ContextProvider.VAR_QUERY_PARAMS, queryParams);
Model model = contextProvider.getRDFModel(
ContextProvider.SYSTEM_COMMANDRESULTS_COLLECTION, params);
tsdb.queryCommandResultsByRange(systemId, null, start, end).subscribe((result) -> {
try {
Map<String, Object> frame = contextProvider.getFrame(
ContextProvider.SYSTEM_COMMANDRESULTS_PARTIAL_COLLECTION, rootURL);
model.add(result);
Resource collection = model.listSubjectsWithProperty(
RDF.type, Hydra.PartialCollectionView).next();
ResIterator iter = model.listSubjectsWithProperty(RDF.type, SEMIOT.CommandResult);
while (iter.hasNext()) {
Resource obs = iter.next();
model.add(collection, Hydra.member, obs);
}
response.resume(JsonUtils.toPrettyString(ModelJsonLdUtils.toJsonLdCompact(model, frame)));
} catch (Throwable e) {
resumeOnError(response, e);
}
}, resumeOnError(response));
}
}
}