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