1 package de.dlr.shepard.context.collection.services;
2
3 import de.dlr.shepard.auth.permission.services.PermissionsService;
4 import de.dlr.shepard.auth.security.AuthenticationContext;
5 import de.dlr.shepard.auth.users.entities.User;
6 import de.dlr.shepard.auth.users.services.UserService;
7 import de.dlr.shepard.common.exceptions.InvalidAuthException;
8 import de.dlr.shepard.common.exceptions.InvalidBodyException;
9 import de.dlr.shepard.common.exceptions.InvalidPathException;
10 import de.dlr.shepard.common.exceptions.InvalidRequestException;
11 import de.dlr.shepard.common.util.DateHelper;
12 import de.dlr.shepard.common.util.QueryParamHelper;
13 import de.dlr.shepard.context.collection.daos.DataObjectDAO;
14 import de.dlr.shepard.context.collection.entities.Collection;
15 import de.dlr.shepard.context.collection.entities.DataObject;
16 import de.dlr.shepard.context.collection.io.DataObjectIO;
17 import de.dlr.shepard.context.references.dataobject.daos.DataObjectReferenceDAO;
18 import de.dlr.shepard.context.references.dataobject.entities.DataObjectReference;
19 import de.dlr.shepard.context.version.services.VersionService;
20 import io.quarkus.logging.Log;
21 import jakarta.enterprise.context.RequestScoped;
22 import jakarta.inject.Inject;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Date;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Set;
29 import java.util.UUID;
30 import java.util.stream.Collectors;
31
32 @RequestScoped
33 public class DataObjectService {
34
35 @Inject
36 DataObjectDAO dataObjectDAO;
37
38 @Inject
39 DataObjectReferenceDAO dataObjectReferenceDAO;
40
41 @Inject
42 UserService userService;
43
44 @Inject
45 DateHelper dateHelper;
46
47 @Inject
48 VersionService versionService;
49
50 @Inject
51 CollectionService collectionService;
52
53 @Inject
54 PermissionsService permissionsService;
55
56 @Inject
57 AuthenticationContext authenticationContext;
58
59
60
61
62
63
64
65
66
67
68
69
70
71 public DataObject createDataObject(long collectionShepardId, DataObjectIO dataObject) throws InvalidBodyException {
72 Collection collection = collectionService.getCollection(collectionShepardId);
73 collectionService.assertIsAllowedToEditCollection(collectionShepardId);
74
75 User user = userService.getCurrentUser();
76 DataObject parent = findRelatedDataObject(collection.getShepardId(), dataObject.getParentId(), null);
77 if (
78 dataObject.getSuccessorIds() != null && dataObject.getSuccessorIds().length != 0
79 ) throw new InvalidBodyException(
80 "when creating a new dataObject the list of successors must not be specified or be empty"
81 );
82 List<DataObject> predecessors = findRelatedDataObjects(
83 collection.getShepardId(),
84 dataObject.getPredecessorIds(),
85 null
86 );
87 DataObject toCreate = new DataObject();
88 toCreate.setAttributes(dataObject.getAttributes());
89 toCreate.setDescription(dataObject.getDescription());
90 toCreate.setName(dataObject.getName());
91 toCreate.setCollection(collection);
92 toCreate.setParent(parent);
93 toCreate.setPredecessors(predecessors);
94 toCreate.setCreatedAt(dateHelper.getDate());
95 toCreate.setCreatedBy(user);
96 DataObject created = dataObjectDAO.createOrUpdate(toCreate);
97 created.setShepardId(created.getId());
98 created = dataObjectDAO.createOrUpdate(created);
99 versionService.attachToVersionOfVersionableEntityAndReturnVersion(collectionShepardId, created.getShepardId());
100 return created;
101 }
102
103
104
105
106
107
108
109
110
111
112 public DataObject getDataObject(long shepardId) {
113 return getDataObject(shepardId, null);
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127 public DataObject getDataObject(long shepardId, UUID versionUID) {
128 DataObject ret;
129 String errorMsg;
130 if (versionUID == null) {
131 ret = dataObjectDAO.findByShepardId(shepardId);
132 errorMsg = "DataObject with id %s is null or deleted".formatted(shepardId);
133 } else {
134 ret = dataObjectDAO.findByShepardId(shepardId, versionUID);
135 errorMsg = "DataObject with id %s and versionUID %s is null or deleted".formatted(shepardId, versionUID);
136 }
137 if (ret == null || ret.isDeleted()) {
138 Log.error(errorMsg);
139 throw new InvalidPathException("ID ERROR - " + errorMsg);
140 }
141
142 collectionService.assertIsAllowedToReadCollection(ret.getCollection().getShepardId());
143 cutDeleted(ret);
144
145 HashSet<Long> incomingReferencesIdList = new HashSet<Long>();
146 for (DataObjectReference reference : ret.getIncoming()) incomingReferencesIdList.add(reference.getId());
147 List<DataObjectReference> completeIncomingReferences = new ArrayList<DataObjectReference>();
148 for (Long id : incomingReferencesIdList) completeIncomingReferences.add(dataObjectReferenceDAO.findByNeo4jId(id));
149
150 HashSet<Long> childrenIdList = new HashSet<Long>();
151 for (DataObject child : ret.getChildren()) childrenIdList.add(child.getId());
152 List<DataObject> completeChildren = new ArrayList<DataObject>();
153 for (Long id : childrenIdList) completeChildren.add(dataObjectDAO.findByNeo4jId(id));
154
155 HashSet<Long> predecessorsIdList = new HashSet<Long>();
156 for (DataObject predecessor : ret.getPredecessors()) predecessorsIdList.add(predecessor.getId());
157 List<DataObject> completePredecessors = new ArrayList<DataObject>();
158 for (Long id : predecessorsIdList) completePredecessors.add(dataObjectDAO.findByNeo4jId(id));
159
160 HashSet<Long> successorsIdList = new HashSet<Long>();
161 for (DataObject successor : ret.getSuccessors()) successorsIdList.add(successor.getId());
162 List<DataObject> completeSuccessors = new ArrayList<DataObject>();
163 for (Long id : successorsIdList) completeSuccessors.add(dataObjectDAO.findByNeo4jId(id));
164
165 ret.setChildren(completeChildren);
166 ret.setIncoming(completeIncomingReferences);
167 ret.setPredecessors(completePredecessors);
168 ret.setSuccessors(completeSuccessors);
169 if (ret.getParent() != null) ret.setParent(dataObjectDAO.findByNeo4jId(ret.getParent().getId()));
170 return ret;
171 }
172
173
174
175
176
177
178
179
180
181
182
183
184 public DataObject getDataObject(long collectionShepardId, long shepardId) {
185 return getDataObject(collectionShepardId, shepardId, null);
186 }
187
188
189
190
191
192
193
194
195
196
197
198
199
200 public DataObject getDataObject(long shepardCollectionId, long shepardId, UUID versionUID) {
201 collectionService.getCollection(shepardCollectionId);
202
203 DataObject dataObject;
204 try {
205
206
207
208 dataObject = getDataObject(shepardId, versionUID);
209 } catch (InvalidAuthException ex) {
210 throw new InvalidPathException("ID ERROR - There is no association between collection and dataObject");
211 }
212
213 if (!dataObject.getCollection().getShepardId().equals(shepardCollectionId)) {
214 throw new InvalidPathException("ID ERROR - There is no association between collection and dataObject");
215 }
216 return dataObject;
217 }
218
219
220
221
222
223
224
225
226
227
228
229
230
231 public List<DataObject> getAllDataObjectsByShepardIds(
232 long collectionShepardId,
233 QueryParamHelper paramsWithShepardIds,
234 UUID versionUID
235 ) {
236 collectionService.getCollection(collectionShepardId, versionUID);
237
238 var unfiltered = dataObjectDAO.findByCollectionByShepardIds(collectionShepardId, paramsWithShepardIds, versionUID);
239 var dataObjects = unfiltered.stream().map(this::cutDeleted).toList();
240 return dataObjects;
241 }
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258 public DataObject updateDataObject(long collectionShepardId, long dataObjectShepardId, DataObjectIO dataObject) {
259 DataObject old = getDataObject(collectionShepardId, dataObjectShepardId);
260 collectionService.assertIsAllowedToEditCollection(collectionShepardId);
261
262 User user = userService.getCurrentUser();
263
264 if (old.getParent() != null) dataObjectDAO.deleteHasChildRelation(
265 old.getParent().getShepardId(),
266 old.getShepardId()
267 );
268
269 if (old.getPredecessors() != null) old
270 .getPredecessors()
271 .forEach(predecessor -> {
272 dataObjectDAO.deleteHasSuccessorRelation(predecessor.getShepardId(), old.getShepardId());
273 });
274
275 if (dataObject.getSuccessorIds() != null) {
276 Set<Long> givenSuccessorIds = Arrays.stream(dataObject.getSuccessorIds()).boxed().collect(Collectors.toSet());
277 Set<Long> foundSuccessorIds = old.getSuccessors().stream().map(DataObject::getId).collect(Collectors.toSet());
278 if (!givenSuccessorIds.equals(foundSuccessorIds)) throw new InvalidBodyException(
279 "the given list of successors does not match the current list of successors"
280 );
281 }
282 dataObjectDAO.deleteAllAttributes(old);
283
284 DataObject newParent = findRelatedDataObject(
285 old.getCollection().getShepardId(),
286 dataObject.getParentId(),
287 dataObjectShepardId
288 );
289 List<DataObject> newPredecessors = findRelatedDataObjects(
290 old.getCollection().getShepardId(),
291 dataObject.getPredecessorIds(),
292 dataObjectShepardId
293 );
294
295 old.setShepardId(old.getShepardId());
296 old.setName(dataObject.getName());
297 old.setDescription(dataObject.getDescription());
298 old.setAttributes(dataObject.getAttributes());
299 old.setParent(newParent);
300 old.setPredecessors(newPredecessors);
301 old.setUpdatedAt(dateHelper.getDate());
302 old.setUpdatedBy(user);
303 DataObject updated = dataObjectDAO.createOrUpdate(old);
304 cutDeleted(updated);
305 return updated;
306 }
307
308
309
310
311
312
313
314
315
316
317
318
319
320 public void deleteDataObject(long collectionShepardId, long dataObjectShepardId) {
321 getDataObject(collectionShepardId, dataObjectShepardId);
322 collectionService.assertIsAllowedToEditCollection(collectionShepardId);
323
324 Date date = dateHelper.getDate();
325 User user = userService.getCurrentUser();
326
327 if (!dataObjectDAO.deleteDataObjectByShepardId(dataObjectShepardId, user, date)) {
328 throw new InvalidRequestException("Could not delete DataObject with ShepardId %s".formatted(dataObjectShepardId));
329 }
330 }
331
332 private DataObject cutDeleted(DataObject dataObject) {
333 var incoming = dataObject.getIncoming().stream().filter(i -> !i.isDeleted()).toList();
334 dataObject.setIncoming(incoming);
335 if (dataObject.getParent() != null && dataObject.getParent().isDeleted()) {
336 dataObject.setParent(null);
337 }
338 var children = dataObject.getChildren().stream().filter(s -> !s.isDeleted()).toList();
339 dataObject.setChildren(children);
340 var predecessors = dataObject.getPredecessors().stream().filter(s -> !s.isDeleted()).toList();
341 dataObject.setPredecessors(predecessors);
342 var successors = dataObject.getSuccessors().stream().filter(s -> !s.isDeleted()).toList();
343 dataObject.setSuccessors(successors);
344 var references = dataObject.getReferences().stream().filter(ref -> !ref.isDeleted()).toList();
345 dataObject.setReferences(references);
346 return dataObject;
347 }
348
349 private List<DataObject> findRelatedDataObjects(
350 long collectionShepardId,
351 long[] referencedShepardIds,
352 Long dataObjectShepardId
353 ) {
354 if (referencedShepardIds == null) return new ArrayList<>();
355
356 var result = new ArrayList<DataObject>(referencedShepardIds.length);
357
358
359
360
361
362 for (var shepardId : referencedShepardIds) {
363 result.add(findRelatedDataObject(collectionShepardId, shepardId, dataObjectShepardId));
364 }
365 return result;
366 }
367
368 private DataObject findRelatedDataObject(
369 long collectionShepardId,
370 Long referencedShepardId,
371 Long dataObjectShepardId
372 ) {
373 if (referencedShepardId == null) return null;
374 else if (referencedShepardId.equals(dataObjectShepardId)) throw new InvalidBodyException(
375 "Self references are not allowed."
376 );
377
378 var dataObject = dataObjectDAO.findByShepardId(referencedShepardId);
379 if (dataObject == null || dataObject.isDeleted()) throw new InvalidBodyException(
380 "The DataObject with id %d could not be found.".formatted(referencedShepardId)
381 );
382
383
384 if (!dataObject.getCollection().getShepardId().equals(collectionShepardId)) throw new InvalidBodyException(
385 "Related data objects must belong to the same collection as the new data object"
386 );
387
388 return dataObject;
389 }
390
391
392
393
394 public void clearSession() {
395 dataObjectDAO.clearSession();
396 }
397 }