1 package de.dlr.shepard.context.references.timeseriesreference.services;
2
3 import de.dlr.shepard.auth.permission.services.PermissionsService;
4 import de.dlr.shepard.auth.users.entities.User;
5 import de.dlr.shepard.auth.users.services.UserService;
6 import de.dlr.shepard.common.exceptions.InvalidAuthException;
7 import de.dlr.shepard.common.exceptions.InvalidPathException;
8 import de.dlr.shepard.common.exceptions.InvalidRequestException;
9 import de.dlr.shepard.common.util.DateHelper;
10 import de.dlr.shepard.context.collection.entities.DataObject;
11 import de.dlr.shepard.context.collection.services.CollectionService;
12 import de.dlr.shepard.context.collection.services.DataObjectService;
13 import de.dlr.shepard.context.references.IReferenceService;
14 import de.dlr.shepard.context.references.timeseriesreference.daos.ReferencedTimeseriesNodeEntityDAO;
15 import de.dlr.shepard.context.references.timeseriesreference.daos.TimeseriesReferenceDAO;
16 import de.dlr.shepard.context.references.timeseriesreference.io.TimeseriesReferenceIO;
17 import de.dlr.shepard.context.references.timeseriesreference.model.ReferencedTimeseriesNodeEntity;
18 import de.dlr.shepard.context.references.timeseriesreference.model.TimeseriesReference;
19 import de.dlr.shepard.context.version.services.VersionService;
20 import de.dlr.shepard.data.timeseries.io.TimeseriesWithDataPoints;
21 import de.dlr.shepard.data.timeseries.model.Timeseries;
22 import de.dlr.shepard.data.timeseries.model.TimeseriesContainer;
23 import de.dlr.shepard.data.timeseries.model.TimeseriesDataPointsQueryParams;
24 import de.dlr.shepard.data.timeseries.model.enums.AggregateFunction;
25 import de.dlr.shepard.data.timeseries.model.enums.FillOption;
26 import de.dlr.shepard.data.timeseries.services.TimeseriesContainerService;
27 import de.dlr.shepard.data.timeseries.services.TimeseriesCsvService;
28 import de.dlr.shepard.data.timeseries.services.TimeseriesService;
29 import de.dlr.shepard.data.timeseries.utilities.TimeseriesValidator;
30 import io.quarkus.logging.Log;
31 import jakarta.enterprise.context.RequestScoped;
32 import jakarta.inject.Inject;
33 import jakarta.ws.rs.NotFoundException;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.util.Collections;
37 import java.util.List;
38 import java.util.Set;
39 import java.util.UUID;
40
41 @RequestScoped
42 public class TimeseriesReferenceService implements IReferenceService<TimeseriesReference, TimeseriesReferenceIO> {
43
44 @Inject
45 TimeseriesReferenceDAO timeseriesReferenceDAO;
46
47 @Inject
48 TimeseriesService timeseriesService;
49
50 @Inject
51 TimeseriesCsvService timeseriesCsvService;
52
53 @Inject
54 DataObjectService dataObjectService;
55
56 @Inject
57 ReferencedTimeseriesNodeEntityDAO timeseriesDAO;
58
59 @Inject
60 UserService userService;
61
62 @Inject
63 CollectionService collectionService;
64
65 @Inject
66 TimeseriesContainerService timeseriesContainerService;
67
68 @Inject
69 VersionService versionService;
70
71 @Inject
72 DateHelper dateHelper;
73
74 @Inject
75 PermissionsService permissionsService;
76
77
78
79
80
81
82
83
84
85
86
87 @Override
88 public List<TimeseriesReference> getAllReferencesByDataObjectId(
89 long collectionShepardId,
90 long dataObjectShepardId,
91 UUID versionUID
92 ) {
93 dataObjectService.getDataObject(collectionShepardId, dataObjectShepardId, versionUID);
94
95 var references = timeseriesReferenceDAO.findByDataObjectShepardId(dataObjectShepardId);
96 return references;
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110 @Override
111 public TimeseriesReference getReference(
112 long collectionShepardId,
113 long dataObjectShepardId,
114 long shepardId,
115 UUID versionUID
116 ) {
117 dataObjectService.getDataObject(collectionShepardId, dataObjectShepardId, versionUID);
118
119 TimeseriesReference reference = timeseriesReferenceDAO.findByShepardId(shepardId, versionUID);
120 if (reference == null || reference.isDeleted()) {
121 String errorMsg = String.format("ID ERROR - Timeseries Reference with id %s is null or deleted", shepardId);
122 Log.error(errorMsg);
123 throw new InvalidPathException(errorMsg);
124 }
125
126 if (reference.getDataObject() == null || !reference.getDataObject().getShepardId().equals(dataObjectShepardId)) {
127 String errorMsg = "ID ERROR - There is no association between dataObject and reference";
128 Log.error(errorMsg);
129 throw new InvalidPathException(errorMsg);
130 }
131
132 return reference;
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146 @Override
147 public TimeseriesReference createReference(
148 long collectionShepardId,
149 long dataObjectShepardId,
150 TimeseriesReferenceIO timeseriesReference
151 ) {
152 DataObject dataObject = dataObjectService.getDataObject(collectionShepardId, dataObjectShepardId);
153 collectionService.assertIsAllowedToEditCollection(collectionShepardId);
154
155 User user = userService.getCurrentUser();
156
157 TimeseriesContainer container;
158 try {
159 container = timeseriesContainerService.getContainer(timeseriesReference.getTimeseriesContainerId());
160 } catch (InvalidPathException ex) {
161 Log.error(ex.getMessage());
162 throw new InvalidRequestException(ex.getMessage());
163 }
164
165
166 timeseriesReference
167 .getTimeseries()
168 .forEach(timeseries -> TimeseriesValidator.assertTimeseriesPropertiesAreValid(timeseries));
169
170 var toCreate = new TimeseriesReference();
171 toCreate.setCreatedAt(dateHelper.getDate());
172 toCreate.setCreatedBy(user);
173 toCreate.setDataObject(dataObject);
174 toCreate.setName(timeseriesReference.getName());
175 toCreate.setStart(timeseriesReference.getStart());
176 toCreate.setEnd(timeseriesReference.getEnd());
177 toCreate.setTimeseriesContainer(container);
178
179 for (var ts : timeseriesReference.getTimeseries()) {
180 var found = timeseriesDAO.find(
181 ts.getMeasurement(),
182 ts.getDevice(),
183 ts.getLocation(),
184 ts.getSymbolicName(),
185 ts.getField()
186 );
187 if (found != null) {
188 toCreate.addTimeseries(found);
189 } else {
190 toCreate.addTimeseries(new ReferencedTimeseriesNodeEntity(ts));
191 }
192 }
193 TimeseriesReference created = timeseriesReferenceDAO.createOrUpdate(toCreate);
194 created.setShepardId(created.getId());
195 created = timeseriesReferenceDAO.createOrUpdate(created);
196 versionService.attachToVersionOfVersionableEntityAndReturnVersion(dataObject.getId(), created.getId());
197 return created;
198 }
199
200
201
202
203
204
205
206
207
208
209 @Override
210 public void deleteReference(long collectionShepardId, long dataObjectShepardId, long timeseriesReferenceShepardId) {
211 TimeseriesReference timeseriesReference = getReference(
212 collectionShepardId,
213 dataObjectShepardId,
214 timeseriesReferenceShepardId,
215 null
216 );
217 collectionService.assertIsAllowedToEditCollection(collectionShepardId);
218
219 User user = userService.getCurrentUser();
220 timeseriesReference.setDeleted(true);
221 timeseriesReference.setUpdatedAt(dateHelper.getDate());
222 timeseriesReference.setUpdatedBy(user);
223 timeseriesReferenceDAO.createOrUpdate(timeseriesReference);
224 }
225
226 public List<TimeseriesWithDataPoints> getReferencedTimeseriesWithDataPointsList(
227 long collectionShepardId,
228 long dataObjectShepardId,
229 long timeseriesShepardId,
230 AggregateFunction function,
231 Long timeSliceNanoseconds,
232 FillOption fillOption,
233 Set<String> devicesFilterSet,
234 Set<String> locationsFilterSet,
235 Set<String> symbolicNameFilterSet
236 ) {
237 TimeseriesReference reference = getReference(collectionShepardId, dataObjectShepardId, timeseriesShepardId, null);
238
239 if (reference.getTimeseriesContainer() == null || reference.getTimeseriesContainer().isDeleted()) {
240 String errorMsg = String.format(
241 "Referenced Timeseries Container from reference with id %s is null or has been deleted",
242 timeseriesShepardId
243 );
244 Log.error(errorMsg);
245 throw new NotFoundException(errorMsg);
246 }
247
248 try {
249
250 timeseriesContainerService.getContainer(reference.getTimeseriesContainer().getId());
251 } catch (InvalidPathException ex) {
252 throw new NotFoundException(ex.getMessage());
253 }
254
255 var timeseriesList = reference.getReferencedTimeseriesList().stream().map(ts -> ts.toTimeseries()).toList();
256 var filteredTimeseriesList = timeseriesList
257 .stream()
258 .filter(timeseries -> matchFilter(timeseries, devicesFilterSet, locationsFilterSet, symbolicNameFilterSet))
259 .toList();
260 var containerId = reference.getTimeseriesContainer().getId();
261 TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
262 reference.getStart(),
263 reference.getEnd(),
264 timeSliceNanoseconds,
265 fillOption,
266 function
267 );
268
269 return timeseriesService.getManyTimeseriesWithDataPoints(containerId, filteredTimeseriesList, queryParams);
270 }
271
272 public InputStream exportReferencedTimeseriesByShepardId(
273 long collectionShepardId,
274 long dataObjectShepardId,
275 long timeseriesShepardId,
276 AggregateFunction function,
277 Long timeSliceNanoseconds,
278 FillOption fillOption,
279 Set<String> devicesFilterSet,
280 Set<String> locationsFilterSet,
281 Set<String> symbolicNameFilterSet
282 ) throws IOException {
283 TimeseriesReference reference = getReference(collectionShepardId, dataObjectShepardId, timeseriesShepardId, null);
284
285 if (reference.getTimeseriesContainer() == null || reference.getTimeseriesContainer().isDeleted()) {
286 String errorMsg = String.format(
287 "The referenced TimeseriesContainer is null or deleted for Reference with id %s",
288 timeseriesShepardId
289 );
290 Log.error(errorMsg);
291 throw new NotFoundException(errorMsg);
292 }
293
294 try {
295 timeseriesContainerService.getContainer(reference.getTimeseriesContainer().getId());
296 } catch (InvalidPathException ex) {
297 throw new InvalidRequestException(ex.getMessage());
298 }
299
300 var timeseriesList = reference.getReferencedTimeseriesList().stream().map(ts -> ts.toTimeseries()).toList();
301 var filteredTimeseriesList = timeseriesList
302 .stream()
303 .filter(timeseries -> matchFilter(timeseries, devicesFilterSet, locationsFilterSet, symbolicNameFilterSet))
304 .toList();
305 var containerId = reference.getTimeseriesContainer().getId();
306 TimeseriesDataPointsQueryParams queryParams = new TimeseriesDataPointsQueryParams(
307 reference.getStart(),
308 reference.getEnd(),
309 timeSliceNanoseconds,
310 fillOption,
311 function
312 );
313
314 return timeseriesCsvService.exportManyTimeseriesWithDataPointsToCsv(
315 containerId,
316 filteredTimeseriesList,
317 queryParams
318 );
319 }
320
321 public InputStream exportReferencedTimeseriesByShepardId(
322 long collectionShepardId,
323 long dataObjectShepardId,
324 long referenceId
325 ) throws IOException {
326 return exportReferencedTimeseriesByShepardId(
327 collectionShepardId,
328 dataObjectShepardId,
329 referenceId,
330 null,
331 null,
332 null,
333 Collections.emptySet(),
334 Collections.emptySet(),
335 Collections.emptySet()
336 );
337 }
338
339 private boolean matchFilter(Timeseries timeseries, Set<String> device, Set<String> location, Set<String> symName) {
340 var deviceMatches = true;
341 var locationMatches = true;
342 var symbolicNameMatches = true;
343 if (!device.isEmpty()) {
344 deviceMatches = device.contains(timeseries.getDevice());
345 }
346 if (!location.isEmpty()) {
347 locationMatches = location.contains(timeseries.getLocation());
348 }
349 if (!symName.isEmpty()) {
350 symbolicNameMatches = symName.contains(timeseries.getSymbolicName());
351 }
352 return deviceMatches && locationMatches && symbolicNameMatches;
353 }
354 }