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