TimeseriesReferenceService.java
package de.dlr.shepard.neo4Core.services;
import de.dlr.shepard.exceptions.InvalidAuthException;
import de.dlr.shepard.exceptions.InvalidBodyException;
import de.dlr.shepard.exceptions.InvalidRequestException;
import de.dlr.shepard.influxDB.FillOption;
import de.dlr.shepard.influxDB.InfluxUtil;
import de.dlr.shepard.influxDB.SingleValuedUnaryFunction;
import de.dlr.shepard.influxDB.TimeseriesPayload;
import de.dlr.shepard.influxDB.TimeseriesService;
import de.dlr.shepard.neo4Core.dao.DataObjectDAO;
import de.dlr.shepard.neo4Core.dao.TimeseriesContainerDAO;
import de.dlr.shepard.neo4Core.dao.TimeseriesDAO;
import de.dlr.shepard.neo4Core.dao.TimeseriesReferenceDAO;
import de.dlr.shepard.neo4Core.dao.UserDAO;
import de.dlr.shepard.neo4Core.dao.VersionDAO;
import de.dlr.shepard.neo4Core.entities.TimeseriesReference;
import de.dlr.shepard.neo4Core.entities.Version;
import de.dlr.shepard.neo4Core.io.TimeseriesReferenceIO;
import de.dlr.shepard.security.PermissionsUtil;
import de.dlr.shepard.util.AccessType;
import de.dlr.shepard.util.DateHelper;
import io.quarkus.logging.Log;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@RequestScoped
public class TimeseriesReferenceService implements IReferenceService<TimeseriesReference, TimeseriesReferenceIO> {
private TimeseriesReferenceDAO timeseriesReferenceDAO;
private TimeseriesService timeseriesService;
private DataObjectDAO dataObjectDAO;
private TimeseriesContainerDAO timeseriesContainerDAO;
private TimeseriesDAO timeseriesDAO;
private UserDAO userDAO;
private VersionDAO versionDAO;
private DateHelper dateHelper;
private PermissionsUtil permissionsUtil;
TimeseriesReferenceService() {}
@Inject
public TimeseriesReferenceService(
TimeseriesReferenceDAO timeseriesReferenceDAO,
TimeseriesService timeseriesService,
DataObjectDAO dataObjectDAO,
TimeseriesContainerDAO timeseriesContainerDAO,
TimeseriesDAO timeseriesDAO,
UserDAO userDAO,
VersionDAO versionDAO,
DateHelper dateHelper,
PermissionsUtil permissionsUtil
) {
this.timeseriesReferenceDAO = timeseriesReferenceDAO;
this.timeseriesService = timeseriesService;
this.dataObjectDAO = dataObjectDAO;
this.timeseriesContainerDAO = timeseriesContainerDAO;
this.timeseriesDAO = timeseriesDAO;
this.userDAO = userDAO;
this.versionDAO = versionDAO;
this.dateHelper = dateHelper;
this.permissionsUtil = permissionsUtil;
}
@Override
public List<TimeseriesReference> getAllReferencesByDataObjectShepardId(long dataObjectShepardId) {
var references = timeseriesReferenceDAO.findByDataObjectShepardId(dataObjectShepardId);
return references;
}
@Override
public TimeseriesReference getReferenceByShepardId(long shepardId) {
var reference = timeseriesReferenceDAO.findByShepardId(shepardId);
if (reference == null || reference.isDeleted()) {
Log.errorf("Timeseries Reference with id %s is null or deleted", shepardId);
return null;
}
return reference;
}
@Override
public TimeseriesReference createReferenceByShepardId(
long dataObjectShepardId,
TimeseriesReferenceIO timeseriesReference,
String username
) {
var user = userDAO.find(username);
var dataObject = dataObjectDAO.findLightByShepardId(dataObjectShepardId);
var container = timeseriesContainerDAO.findLightByNeo4jId(timeseriesReference.getTimeseriesContainerId());
if (container == null || container.isDeleted()) {
throw new InvalidBodyException(
String.format(
"The timeseries container with id %d could not be found.",
timeseriesReference.getTimeseriesContainerId()
)
);
}
// sanitize timeseries
var errors = Arrays.stream(timeseriesReference.getTimeseries())
.map(InfluxUtil::sanitize)
.filter(e -> !e.isBlank())
.toList();
if (!errors.isEmpty()) throw new InvalidBodyException(
"The timeseries list contains illegal characters: " + String.join(", ", errors)
);
var toCreate = new TimeseriesReference();
toCreate.setCreatedAt(dateHelper.getDate());
toCreate.setCreatedBy(user);
toCreate.setDataObject(dataObject);
toCreate.setName(timeseriesReference.getName());
toCreate.setStart(timeseriesReference.getStart());
toCreate.setEnd(timeseriesReference.getEnd());
toCreate.setTimeseriesContainer(container);
for (var ts : timeseriesReference.getTimeseries()) {
var found = timeseriesDAO.find(
ts.getMeasurement(),
ts.getDevice(),
ts.getLocation(),
ts.getSymbolicName(),
ts.getField()
);
if (found != null) {
toCreate.addTimeseries(found);
} else {
toCreate.addTimeseries(ts);
}
}
TimeseriesReference created = timeseriesReferenceDAO.createOrUpdate(toCreate);
created.setShepardId(created.getId());
created = timeseriesReferenceDAO.createOrUpdate(created);
Version version = versionDAO.findVersionLightByNeo4jId(dataObject.getId());
versionDAO.createLink(created.getId(), version.getUid());
return created;
}
@Override
public boolean deleteReferenceByShepardId(long timeseriesShepardId, String username) {
var user = userDAO.find(username);
var old = timeseriesReferenceDAO.findByShepardId(timeseriesShepardId);
old.setDeleted(true);
old.setUpdatedAt(dateHelper.getDate());
old.setUpdatedBy(user);
timeseriesReferenceDAO.createOrUpdate(old);
return true;
}
public List<TimeseriesPayload> getTimeseriesPayloadByShepardId(
long timeseriesShepardId,
SingleValuedUnaryFunction function,
Long groupBy,
FillOption fillOption,
Set<String> devicesFilterSet,
Set<String> locationsFilterSet,
Set<String> symbolicNameFilterSet,
String username
) {
var reference = timeseriesReferenceDAO.findByShepardId(timeseriesShepardId);
if (
reference.getTimeseriesContainer() == null ||
reference.getTimeseriesContainer().isDeleted() ||
!permissionsUtil.isAccessTypeAllowedForUser(reference.getTimeseriesContainer().getId(), AccessType.Read, username)
) return reference.getTimeseries().stream().map(ts -> new TimeseriesPayload(ts, Collections.emptyList())).toList();
var database = reference.getTimeseriesContainer().getDatabase();
return timeseriesService.getTimeseriesPayloadList(
reference.getStart(),
reference.getEnd(),
database,
reference.getTimeseries(),
function,
groupBy,
fillOption,
devicesFilterSet,
locationsFilterSet,
symbolicNameFilterSet
);
}
public InputStream exportTimeseriesPayloadByShepardId(
long timeseriesShepardId,
SingleValuedUnaryFunction function,
Long groupBy,
FillOption fillOption,
Set<String> devicesFilterSet,
Set<String> locationsFilterSet,
Set<String> symbolicNameFilterSet,
String username
) throws IOException {
var reference = timeseriesReferenceDAO.findByShepardId(timeseriesShepardId);
if (
reference.getTimeseriesContainer() == null || reference.getTimeseriesContainer().isDeleted()
) throw new InvalidRequestException("The timeseries container in question is not accessible");
if (
!permissionsUtil.isAccessTypeAllowedForUser(reference.getTimeseriesContainer().getId(), AccessType.Read, username)
) throw new InvalidAuthException("You are not authorized to access this timeseries");
var database = reference.getTimeseriesContainer().getDatabase();
return timeseriesService.exportTimeseriesPayload(
reference.getStart(),
reference.getEnd(),
database,
reference.getTimeseries(),
function,
groupBy,
fillOption,
devicesFilterSet,
locationsFilterSet,
symbolicNameFilterSet
);
}
public InputStream exportTimeseriesPayloadByShepardId(long timeseriesId, String username) throws IOException {
return exportTimeseriesPayloadByShepardId(
timeseriesId,
null,
null,
null,
Collections.emptySet(),
Collections.emptySet(),
Collections.emptySet(),
username
);
}
}