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