View Javadoc
1   package de.dlr.shepard.context.export;
2   
3   import de.dlr.shepard.auth.security.AuthenticationContext;
4   import de.dlr.shepard.common.exceptions.InvalidAuthException;
5   import de.dlr.shepard.common.exceptions.InvalidBodyException;
6   import de.dlr.shepard.common.exceptions.ShepardException;
7   import de.dlr.shepard.common.mongoDB.NamedInputStream;
8   import de.dlr.shepard.context.collection.entities.Collection;
9   import de.dlr.shepard.context.collection.services.CollectionService;
10  import de.dlr.shepard.context.collection.services.DataObjectService;
11  import de.dlr.shepard.context.labJournal.entities.LabJournalEntry;
12  import de.dlr.shepard.context.labJournal.io.LabJournalEntryIO;
13  import de.dlr.shepard.context.labJournal.services.LabJournalEntryService;
14  import de.dlr.shepard.context.references.basicreference.entities.BasicReference;
15  import de.dlr.shepard.context.references.basicreference.io.BasicReferenceIO;
16  import de.dlr.shepard.context.references.basicreference.services.BasicReferenceService;
17  import de.dlr.shepard.context.references.file.entities.FileReference;
18  import de.dlr.shepard.context.references.file.io.FileReferenceIO;
19  import de.dlr.shepard.context.references.file.services.FileReferenceService;
20  import de.dlr.shepard.context.references.structureddata.io.StructuredDataReferenceIO;
21  import de.dlr.shepard.context.references.structureddata.services.StructuredDataReferenceService;
22  import de.dlr.shepard.context.references.timeseriesreference.io.TimeseriesReferenceIO;
23  import de.dlr.shepard.context.references.timeseriesreference.model.TimeseriesReference;
24  import de.dlr.shepard.context.references.timeseriesreference.services.TimeseriesReferenceService;
25  import de.dlr.shepard.context.references.uri.io.URIReferenceIO;
26  import de.dlr.shepard.context.references.uri.services.URIReferenceService;
27  import de.dlr.shepard.data.structureddata.entities.StructuredDataPayload;
28  import de.dlr.shepard.data.timeseries.model.enums.CsvFormat;
29  import io.quarkus.logging.Log;
30  import jakarta.enterprise.context.RequestScoped;
31  import jakarta.inject.Inject;
32  import java.io.IOException;
33  import java.io.InputStream;
34  import java.nio.file.InvalidPathException;
35  import java.util.Collections;
36  import java.util.List;
37  
38  @RequestScoped
39  public class ExportService {
40  
41    @Inject
42    CollectionService collectionService;
43  
44    @Inject
45    DataObjectService dataObjectService;
46  
47    @Inject
48    BasicReferenceService basicReferenceService;
49  
50    @Inject
51    LabJournalEntryService labJournalEntryService;
52  
53    @Inject
54    TimeseriesReferenceService timeseriesReferenceService;
55  
56    @Inject
57    FileReferenceService fileReferenceService;
58  
59    @Inject
60    StructuredDataReferenceService structuredDataReferenceService;
61  
62    @Inject
63    URIReferenceService uriReferenceService;
64  
65    @Inject
66    AuthenticationContext authenticationContext;
67  
68    /**
69     * Exports collection by shepard Id
70     *
71     * @param collectionId
72     * @return InputStream
73     * @throws InvalidPathException if collection with 'collectionId' could not be found
74     * @throws InvalidAuthException if user has no read permissions on collection
75     * @throws IOException if building the InputStream fails
76     */
77    public InputStream exportCollectionByShepardId(long collectionId) throws IOException {
78      Collection collection = collectionService.getCollectionWithDataObjectsAndIncomingReferences(collectionId);
79  
80      var exportBuilder = new ExportBuilder(collection);
81      for (var dataObject : collection.getDataObjects()) {
82        fetchAndWriteDataObject(collectionId, exportBuilder, dataObject.getShepardId());
83      }
84      return exportBuilder.build();
85    }
86  
87    private void fetchAndWriteDataObject(long collectionId, ExportBuilder builder, long dataObjectId)
88      throws IOException, InvalidBodyException {
89      var dataObject = dataObjectService.getDataObject(dataObjectId);
90      builder.addDataObject(dataObject);
91  
92      // TODO: Add more types, maybe improve (StrategyPattern?)
93      for (BasicReference reference : dataObject.getReferences()) {
94        switch (reference.getType()) {
95          case "TimeseriesReference" -> fetchAndWriteTimeseriesReference(
96            collectionId,
97            dataObjectId,
98            builder,
99            reference.getShepardId(),
100           authenticationContext.getCurrentUserName()
101         );
102         case "FileReference" -> fetchAndWriteFileReference(
103           collectionId,
104           dataObjectId,
105           builder,
106           reference.getShepardId()
107         );
108         case "StructuredDataReference" -> fetchAndWriteStructuredDataReference(
109           collectionId,
110           dataObjectId,
111           builder,
112           reference.getShepardId()
113         );
114         case "URIReference" -> fetchAndWriteUriReference(
115           collectionId,
116           dataObjectId,
117           builder,
118           reference.getShepardId(),
119           authenticationContext.getCurrentUserName()
120         );
121         default -> fetchAndWriteBasicReference(collectionId, dataObjectId, builder, reference.getShepardId());
122       }
123     }
124     for (LabJournalEntry entry : dataObject.getLabJournalEntries()) {
125       fetchAndWriteLabJournalEntry(collectionId, dataObjectId, builder, entry.getId());
126     }
127   }
128 
129   private void fetchAndWriteLabJournalEntry(
130     long collectionId,
131     long dataObjectId,
132     ExportBuilder builder,
133     long labJournalEntryId
134   ) throws IOException {
135     LabJournalEntry entry = labJournalEntryService.getLabJournalEntry(labJournalEntryId);
136     builder.addLabJournalEntry(new LabJournalEntryIO(entry), entry.getCreatedBy());
137   }
138 
139   private void fetchAndWriteTimeseriesReference(
140     long collectionShepardId,
141     long dataObjectShepardId,
142     ExportBuilder builder,
143     long referenceId,
144     String username
145   ) throws IOException {
146     var reference = timeseriesReferenceService.getReference(
147       collectionShepardId,
148       dataObjectShepardId,
149       referenceId,
150       null
151     );
152     builder.addReference(new TimeseriesReferenceIO(reference), reference.getCreatedBy());
153     InputStream timeseriesPayload = null;
154     try {
155       timeseriesPayload = timeseriesReferenceService.exportReferencedTimeseriesByShepardId(
156         collectionShepardId,
157         dataObjectShepardId,
158         referenceId,
159         CsvFormat.ROW
160       );
161     } catch (ShepardException e) {
162       Log.warn("Cannot access timeseries payload during export");
163     }
164     if (timeseriesPayload != null) {
165       writeTimeseriesPayload(builder, timeseriesPayload, reference);
166     }
167   }
168 
169   private void fetchAndWriteFileReference(
170     long collectionShepardId,
171     long dataObjectShepardId,
172     ExportBuilder builder,
173     long referenceId
174   ) throws IOException {
175     FileReference reference = fileReferenceService.getReference(
176       collectionShepardId,
177       dataObjectShepardId,
178       referenceId,
179       null
180     );
181 
182     builder.addReference(new FileReferenceIO(reference), reference.getCreatedBy());
183 
184     List<NamedInputStream> payloads = Collections.emptyList();
185     try {
186       payloads = fileReferenceService.getAllPayloads(collectionShepardId, dataObjectShepardId, referenceId);
187     } catch (ShepardException e) {
188       Log.warn("Cannot access file payload during export");
189     }
190 
191     for (var nis : payloads) {
192       if (nis.getInputStream() != null) writeFilePayload(builder, nis);
193     }
194   }
195 
196   private void fetchAndWriteStructuredDataReference(
197     long collectionId,
198     long dataObjectId,
199     ExportBuilder builder,
200     long referenceId
201   ) throws IOException {
202     var reference = structuredDataReferenceService.getReference(collectionId, dataObjectId, referenceId, null);
203 
204     builder.addReference(new StructuredDataReferenceIO(reference), reference.getCreatedBy());
205 
206     List<StructuredDataPayload> payloads = Collections.emptyList();
207     try {
208       payloads = structuredDataReferenceService.getAllPayloads(collectionId, dataObjectId, referenceId);
209     } catch (ShepardException e) {
210       Log.warn("Cannot access structured data payload during export");
211     }
212 
213     for (var sdp : payloads) {
214       if (sdp.getPayload() != null) writeStructuredDataPayload(builder, sdp);
215     }
216   }
217 
218   private void fetchAndWriteUriReference(
219     long collectionShepardId,
220     long dataObjectShepardId,
221     ExportBuilder builder,
222     long referenceId,
223     String username
224   ) throws IOException {
225     var reference = uriReferenceService.getReference(collectionShepardId, dataObjectShepardId, referenceId, null);
226 
227     builder.addReference(new URIReferenceIO(reference), reference.getCreatedBy());
228   }
229 
230   private void fetchAndWriteBasicReference(
231     long collectionShepardId,
232     long dataObjectShepardId,
233     ExportBuilder builder,
234     long referenceId
235   ) throws IOException {
236     var reference = basicReferenceService.getReference(collectionShepardId, dataObjectShepardId, referenceId);
237 
238     builder.addReference(new BasicReferenceIO(reference), reference.getCreatedBy());
239   }
240 
241   private void writeFilePayload(ExportBuilder builder, NamedInputStream nis) throws IOException {
242     var nameSplitted = nis.getName().split("\\.", 2);
243     var filename = nameSplitted.length > 1 ? nis.getOid() + "." + nameSplitted[1] : nis.getOid();
244 
245     builder.addPayload(nis.getInputStream().readAllBytes(), filename, nis.getName());
246   }
247 
248   private void writeStructuredDataPayload(ExportBuilder builder, StructuredDataPayload sdp) throws IOException {
249     var filename = sdp.getStructuredData().getOid() + ExportConstants.JSON_FILE_EXTENSION;
250 
251     builder.addPayload(sdp.getPayload().getBytes(), filename, sdp.getStructuredData().getName(), "application/json");
252   }
253 
254   private void writeTimeseriesPayload(ExportBuilder builder, InputStream payload, TimeseriesReference reference)
255     throws IOException {
256     var filename = reference.getUniqueId() + ExportConstants.CSV_FILE_EXTENSION;
257 
258     builder.addPayload(payload.readAllBytes(), filename, reference.getName(), "text/csv");
259   }
260 }