View Javadoc
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     // sanitize timeseries
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 }