1 package de.dlr.shepard.neo4Core.services;
2
3 import de.dlr.shepard.exceptions.InvalidAuthException;
4 import de.dlr.shepard.exceptions.InvalidBodyException;
5 import de.dlr.shepard.exceptions.InvalidRequestException;
6 import de.dlr.shepard.influxDB.FillOption;
7 import de.dlr.shepard.influxDB.InfluxUtil;
8 import de.dlr.shepard.influxDB.SingleValuedUnaryFunction;
9 import de.dlr.shepard.influxDB.TimeseriesPayload;
10 import de.dlr.shepard.influxDB.TimeseriesService;
11 import de.dlr.shepard.neo4Core.dao.DataObjectDAO;
12 import de.dlr.shepard.neo4Core.dao.TimeseriesContainerDAO;
13 import de.dlr.shepard.neo4Core.dao.TimeseriesDAO;
14 import de.dlr.shepard.neo4Core.dao.TimeseriesReferenceDAO;
15 import de.dlr.shepard.neo4Core.dao.UserDAO;
16 import de.dlr.shepard.neo4Core.dao.VersionDAO;
17 import de.dlr.shepard.neo4Core.entities.TimeseriesReference;
18 import de.dlr.shepard.neo4Core.entities.Version;
19 import de.dlr.shepard.neo4Core.io.TimeseriesReferenceIO;
20 import de.dlr.shepard.security.PermissionsUtil;
21 import de.dlr.shepard.util.AccessType;
22 import de.dlr.shepard.util.DateHelper;
23 import io.quarkus.logging.Log;
24 import jakarta.enterprise.context.RequestScoped;
25 import jakarta.inject.Inject;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.util.Arrays;
29 import java.util.Collections;
30 import java.util.List;
31 import java.util.Set;
32
33 @RequestScoped
34 public class TimeseriesReferenceService implements IReferenceService<TimeseriesReference, TimeseriesReferenceIO> {
35
36 private TimeseriesReferenceDAO timeseriesReferenceDAO;
37 private TimeseriesService timeseriesService;
38 private DataObjectDAO dataObjectDAO;
39 private TimeseriesContainerDAO timeseriesContainerDAO;
40 private TimeseriesDAO timeseriesDAO;
41 private UserDAO userDAO;
42 private VersionDAO versionDAO;
43 private DateHelper dateHelper;
44 private PermissionsUtil permissionsUtil;
45
46 TimeseriesReferenceService() {}
47
48 @Inject
49 public TimeseriesReferenceService(
50 TimeseriesReferenceDAO timeseriesReferenceDAO,
51 TimeseriesService timeseriesService,
52 DataObjectDAO dataObjectDAO,
53 TimeseriesContainerDAO timeseriesContainerDAO,
54 TimeseriesDAO timeseriesDAO,
55 UserDAO userDAO,
56 VersionDAO versionDAO,
57 DateHelper dateHelper,
58 PermissionsUtil permissionsUtil
59 ) {
60 this.timeseriesReferenceDAO = timeseriesReferenceDAO;
61 this.timeseriesService = timeseriesService;
62 this.dataObjectDAO = dataObjectDAO;
63 this.timeseriesContainerDAO = timeseriesContainerDAO;
64 this.timeseriesDAO = timeseriesDAO;
65 this.userDAO = userDAO;
66 this.versionDAO = versionDAO;
67 this.dateHelper = dateHelper;
68 this.permissionsUtil = permissionsUtil;
69 }
70
71 @Override
72 public List<TimeseriesReference> getAllReferencesByDataObjectShepardId(long dataObjectShepardId) {
73 var references = timeseriesReferenceDAO.findByDataObjectShepardId(dataObjectShepardId);
74 return references;
75 }
76
77 @Override
78 public TimeseriesReference getReferenceByShepardId(long shepardId) {
79 var reference = timeseriesReferenceDAO.findByShepardId(shepardId);
80 if (reference == null || reference.isDeleted()) {
81 Log.errorf("Timeseries Reference with id %s is null or deleted", shepardId);
82 return null;
83 }
84 return reference;
85 }
86
87 @Override
88 public TimeseriesReference createReferenceByShepardId(
89 long dataObjectShepardId,
90 TimeseriesReferenceIO timeseriesReference,
91 String username
92 ) {
93 var user = userDAO.find(username);
94 var dataObject = dataObjectDAO.findLightByShepardId(dataObjectShepardId);
95 var container = timeseriesContainerDAO.findLightByNeo4jId(timeseriesReference.getTimeseriesContainerId());
96 if (container == null || container.isDeleted()) {
97 throw new InvalidBodyException(
98 String.format(
99 "The timeseries container with id %d could not be found.",
100 timeseriesReference.getTimeseriesContainerId()
101 )
102 );
103 }
104
105 var errors = Arrays.stream(timeseriesReference.getTimeseries())
106 .map(InfluxUtil::sanitize)
107 .filter(e -> !e.isBlank())
108 .toList();
109 if (!errors.isEmpty()) throw new InvalidBodyException(
110 "The timeseries list contains illegal characters: " + String.join(", ", errors)
111 );
112 var toCreate = new TimeseriesReference();
113 toCreate.setCreatedAt(dateHelper.getDate());
114 toCreate.setCreatedBy(user);
115 toCreate.setDataObject(dataObject);
116 toCreate.setName(timeseriesReference.getName());
117 toCreate.setStart(timeseriesReference.getStart());
118 toCreate.setEnd(timeseriesReference.getEnd());
119 toCreate.setTimeseriesContainer(container);
120
121 for (var ts : timeseriesReference.getTimeseries()) {
122 var found = timeseriesDAO.find(
123 ts.getMeasurement(),
124 ts.getDevice(),
125 ts.getLocation(),
126 ts.getSymbolicName(),
127 ts.getField()
128 );
129 if (found != null) {
130 toCreate.addTimeseries(found);
131 } else {
132 toCreate.addTimeseries(ts);
133 }
134 }
135 TimeseriesReference created = timeseriesReferenceDAO.createOrUpdate(toCreate);
136 created.setShepardId(created.getId());
137 created = timeseriesReferenceDAO.createOrUpdate(created);
138 Version version = versionDAO.findVersionLightByNeo4jId(dataObject.getId());
139 versionDAO.createLink(created.getId(), version.getUid());
140 return created;
141 }
142
143 @Override
144 public boolean deleteReferenceByShepardId(long timeseriesShepardId, String username) {
145 var user = userDAO.find(username);
146
147 var old = timeseriesReferenceDAO.findByShepardId(timeseriesShepardId);
148 old.setDeleted(true);
149 old.setUpdatedAt(dateHelper.getDate());
150 old.setUpdatedBy(user);
151
152 timeseriesReferenceDAO.createOrUpdate(old);
153 return true;
154 }
155
156 public List<TimeseriesPayload> getTimeseriesPayloadByShepardId(
157 long timeseriesShepardId,
158 SingleValuedUnaryFunction function,
159 Long groupBy,
160 FillOption fillOption,
161 Set<String> devicesFilterSet,
162 Set<String> locationsFilterSet,
163 Set<String> symbolicNameFilterSet,
164 String username
165 ) {
166 var reference = timeseriesReferenceDAO.findByShepardId(timeseriesShepardId);
167 if (
168 reference.getTimeseriesContainer() == null ||
169 reference.getTimeseriesContainer().isDeleted() ||
170 !permissionsUtil.isAccessTypeAllowedForUser(reference.getTimeseriesContainer().getId(), AccessType.Read, username)
171 ) return reference.getTimeseries().stream().map(ts -> new TimeseriesPayload(ts, Collections.emptyList())).toList();
172
173 var database = reference.getTimeseriesContainer().getDatabase();
174 return timeseriesService.getTimeseriesPayloadList(
175 reference.getStart(),
176 reference.getEnd(),
177 database,
178 reference.getTimeseries(),
179 function,
180 groupBy,
181 fillOption,
182 devicesFilterSet,
183 locationsFilterSet,
184 symbolicNameFilterSet
185 );
186 }
187
188 public InputStream exportTimeseriesPayloadByShepardId(
189 long timeseriesShepardId,
190 SingleValuedUnaryFunction function,
191 Long groupBy,
192 FillOption fillOption,
193 Set<String> devicesFilterSet,
194 Set<String> locationsFilterSet,
195 Set<String> symbolicNameFilterSet,
196 String username
197 ) throws IOException {
198 var reference = timeseriesReferenceDAO.findByShepardId(timeseriesShepardId);
199 if (
200 reference.getTimeseriesContainer() == null || reference.getTimeseriesContainer().isDeleted()
201 ) throw new InvalidRequestException("The timeseries container in question is not accessible");
202 if (
203 !permissionsUtil.isAccessTypeAllowedForUser(reference.getTimeseriesContainer().getId(), AccessType.Read, username)
204 ) throw new InvalidAuthException("You are not authorized to access this timeseries");
205
206 var database = reference.getTimeseriesContainer().getDatabase();
207
208 return timeseriesService.exportTimeseriesPayload(
209 reference.getStart(),
210 reference.getEnd(),
211 database,
212 reference.getTimeseries(),
213 function,
214 groupBy,
215 fillOption,
216 devicesFilterSet,
217 locationsFilterSet,
218 symbolicNameFilterSet
219 );
220 }
221
222 public InputStream exportTimeseriesPayloadByShepardId(long timeseriesId, String username) throws IOException {
223 return exportTimeseriesPayloadByShepardId(
224 timeseriesId,
225 null,
226 null,
227 null,
228 Collections.emptySet(),
229 Collections.emptySet(),
230 Collections.emptySet(),
231 username
232 );
233 }
234 }