1
1
/*
2
2
* SORMAS® - Surveillance Outbreak Response Management & Analysis System
3
- * Copyright © 2016-2023 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI)
3
+ * Copyright © 2016-2026 SORMAS Foundation gGmbH
4
4
* This program is free software: you can redistribute it and/or modify
5
5
* it under the terms of the GNU General Public License as published by
6
6
* the Free Software Foundation, either version 3 of the License, or
15
15
16
16
package de .symeda .sormas .api .externalmessage .processing .labmessage ;
17
17
18
+ import java .util .ArrayList ;
18
19
import java .util .Date ;
20
+ import java .util .List ;
19
21
20
22
import org .slf4j .Logger ;
21
23
import org .slf4j .LoggerFactory ;
22
24
25
+ import com .fasterxml .jackson .core .type .TypeReference ;
26
+ import com .fasterxml .jackson .databind .ObjectMapper ;
27
+
28
+ import de .symeda .sormas .api .activityascase .ActivityAsCaseDto ;
29
+ import de .symeda .sormas .api .activityascase .ActivityAsCaseType ;
23
30
import de .symeda .sormas .api .caze .CaseDataDto ;
24
31
import de .symeda .sormas .api .caze .CaseOutcome ;
25
32
import de .symeda .sormas .api .caze .CaseSelectionDto ;
26
33
import de .symeda .sormas .api .caze .InvestigationStatus ;
27
34
import de .symeda .sormas .api .caze .surveillancereport .SurveillanceReportDto ;
28
35
import de .symeda .sormas .api .contact .ContactDto ;
29
36
import de .symeda .sormas .api .contact .SimilarContactDto ;
37
+ import de .symeda .sormas .api .epidata .EpiDataDto ;
30
38
import de .symeda .sormas .api .event .EventDto ;
31
39
import de .symeda .sormas .api .event .EventParticipantDto ;
32
40
import de .symeda .sormas .api .event .SimilarEventParticipantDto ;
41
+ import de .symeda .sormas .api .exposure .ExposureDto ;
42
+ import de .symeda .sormas .api .exposure .ExposureType ;
33
43
import de .symeda .sormas .api .externalmessage .ExternalMessageDto ;
34
44
import de .symeda .sormas .api .externalmessage .ExternalMessageStatus ;
35
45
import de .symeda .sormas .api .externalmessage .processing .AbstractMessageProcessingFlowBase ;
45
55
import de .symeda .sormas .api .therapy .TreatmentDto ;
46
56
import de .symeda .sormas .api .user .UserDto ;
47
57
import de .symeda .sormas .api .utils .DtoCopyHelper ;
58
+ import de .symeda .sormas .api .utils .YesNoUnknown ;
48
59
import de .symeda .sormas .api .utils .dataprocessing .ProcessingResult ;
49
60
import de .symeda .sormas .api .utils .dataprocessing .flow .FlowThen ;
50
61
@@ -231,11 +242,21 @@ protected void postBuildCase(CaseDataDto caseDto, ExternalMessageDto externalMes
231
242
232
243
postBuildCaseSymptoms (caseDto , externalMessageDto );
233
244
postBuildCaseTherapy (caseDto , externalMessageDto );
245
+ postBuildActivitiesAsCase (caseDto , externalMessageDto );
246
+ postBuildExposure (caseDto , externalMessageDto );
234
247
235
248
caseDto .setInvestigationStatus (InvestigationStatus .PENDING );
236
249
caseDto .setOutcome (CaseOutcome .NO_OUTCOME );
237
250
}
238
251
252
+ /**
253
+ * Sets the symptoms for the case from the external message, if present.
254
+ *
255
+ * @param caseDto
256
+ * The case data transfer object to update.
257
+ * @param externalMessageDto
258
+ * The external message containing symptom data.
259
+ */
239
260
protected void postBuildCaseSymptoms (CaseDataDto caseDto , ExternalMessageDto externalMessageDto ) {
240
261
if (externalMessageDto .getCaseSymptoms () != null ) {
241
262
final SymptomsDto symptomsDto = SymptomsDto .build ();
@@ -246,6 +267,14 @@ protected void postBuildCaseSymptoms(CaseDataDto caseDto, ExternalMessageDto ext
246
267
}
247
268
}
248
269
270
+ /**
271
+ * Sets the therapy information for the case from the external message, if present.
272
+ *
273
+ * @param caseDto
274
+ * The case data transfer object to update.
275
+ * @param externalMessageDto
276
+ * The external message containing therapy data.
277
+ */
249
278
protected void postBuildCaseTherapy (CaseDataDto caseDto , ExternalMessageDto externalMessageDto ) {
250
279
251
280
TherapyDto therapyDto = caseDto .getTherapy ();
@@ -258,6 +287,112 @@ protected void postBuildCaseTherapy(CaseDataDto caseDto, ExternalMessageDto exte
258
287
259
288
}
260
289
290
+ /**
291
+ * Sets the activities as case for the case from the external message, if present.
292
+ * <p>
293
+ * This method deserializes the activities as case from a JSON string in the external message
294
+ * into a list of {@link ActivityAsCaseDto} objects. Each activity is built and copied, and if
295
+ * the activity type is missing, it is set to {@link ActivityAsCaseType#UNKNOWN}.
296
+ * If there are activities, the {@code activityAsCaseDetailsKnown} field is set to {@link YesNoUnknown#YES}.
297
+ * </p>
298
+ *
299
+ * @param caseDto
300
+ * The case data transfer object to update.
301
+ * @param externalMessageDto
302
+ * The external message containing activities as case data in JSON format.
303
+ */
304
+ protected void postBuildActivitiesAsCase (CaseDataDto caseDto , ExternalMessageDto externalMessageDto ) {
305
+
306
+ if (externalMessageDto .getActivitiesAsCase () != null && !externalMessageDto .getActivitiesAsCase ().isEmpty ()) {
307
+ final ArrayList <ActivityAsCaseDto > activitiesAsCase = new ArrayList <>();
308
+
309
+ try {
310
+ ObjectMapper objectMapper = new ObjectMapper ();
311
+ List <ActivityAsCaseDto > deserialActivityAsCaseDtos =
312
+ objectMapper .readValue (externalMessageDto .getActivitiesAsCase (), new TypeReference <List <ActivityAsCaseDto >>() {
313
+ });
314
+ for (ActivityAsCaseDto activityAsCaseDto : deserialActivityAsCaseDtos ) {
315
+ ActivityAsCaseDto newActivityAsCase = ActivityAsCaseDto .build (activityAsCaseDto .getActivityAsCaseType ());
316
+ if (newActivityAsCase .getActivityAsCaseType () == null ) {
317
+ newActivityAsCase .setActivityAsCaseType (ActivityAsCaseType .UNKNOWN );
318
+ }
319
+ DtoCopyHelper .copyDtoValues (newActivityAsCase , activityAsCaseDto , true , "uuid" );
320
+ activitiesAsCase .add (newActivityAsCase );
321
+ }
322
+ } catch (Exception e ) {
323
+ logger .error ("[POST BUILD CASE] Error while processing activities as case for case with UUID: {}" , caseDto .getUuid (), e );
324
+ return ;
325
+ }
326
+
327
+ if (!activitiesAsCase .isEmpty ()) {
328
+ EpiDataDto epiData = caseDto .getEpiData ();
329
+ if (epiData == null ) {
330
+ epiData = EpiDataDto .build ();
331
+ caseDto .setEpiData (epiData );
332
+ }
333
+
334
+ epiData .setActivityAsCaseDetailsKnown (YesNoUnknown .YES );
335
+ epiData .setActivitiesAsCase (activitiesAsCase );
336
+ }
337
+
338
+ } else {
339
+ logger .debug ("[POST BUILD CASE] No activities to set for case with UUID: {}" , caseDto .getUuid ());
340
+ }
341
+ }
342
+
343
+ /**
344
+ * Sets the exposure information for the case from the external message, if present.
345
+ * <p>
346
+ * This method deserializes the exposures from a JSON string in the external message
347
+ * into a list of {@link ExposureDto} objects. Each exposure is built and copied, and if
348
+ * the exposure type is missing, it is set to {@link ExposureType#UNKNOWN}.
349
+ * If there are exposures, the {@code exposureDetailsKnown} field is set to {@link YesNoUnknown#YES}.
350
+ * </p>
351
+ *
352
+ * @param caseDto
353
+ * The case data transfer object to update.
354
+ * @param externalMessageDto
355
+ * The external message containing exposure data in JSON format.
356
+ */
357
+ protected void postBuildExposure (CaseDataDto caseDto , ExternalMessageDto externalMessageDto ) {
358
+
359
+ if (externalMessageDto .getExposures () != null && !externalMessageDto .getExposures ().isEmpty ()) {
360
+ final ArrayList <ExposureDto > exposures = new ArrayList <>();
361
+
362
+ try {
363
+ ObjectMapper objectMapper = new ObjectMapper ();
364
+ List <ExposureDto > deserialExposureDtos =
365
+ objectMapper .readValue (externalMessageDto .getExposures (), new TypeReference <List <ExposureDto >>() {
366
+ });
367
+ for (ExposureDto exposureDto : deserialExposureDtos ) {
368
+ ExposureDto newExposure = ExposureDto .build (exposureDto .getExposureType ());
369
+ if (newExposure .getExposureType () == null ) {
370
+ newExposure .setExposureType (ExposureType .UNKNOWN );
371
+ }
372
+ DtoCopyHelper .copyDtoValues (newExposure , exposureDto , true , "uuid" );
373
+ exposures .add (newExposure );
374
+ }
375
+ } catch (Exception e ) {
376
+ logger .error ("[POST BUILD CASE] Error while processing exposures for case with UUID: {}" , caseDto .getUuid (), e );
377
+ return ;
378
+ }
379
+
380
+ if (!exposures .isEmpty ()) {
381
+ EpiDataDto epiData = caseDto .getEpiData ();
382
+ if (epiData == null ) {
383
+ epiData = EpiDataDto .build ();
384
+ caseDto .setEpiData (epiData );
385
+ }
386
+
387
+ epiData .setExposureDetailsKnown (YesNoUnknown .YES );
388
+ epiData .setExposures (exposures );
389
+ }
390
+
391
+ } else {
392
+ logger .debug ("[POST BUILD CASE] No exposures to set for case with UUID: {}" , caseDto .getUuid ());
393
+ }
394
+ }
395
+
261
396
/**
262
397
* Custom logic to execute after building a person.
263
398
*
0 commit comments