Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions sormas-api/src/main/java/de/symeda/sormas/api/Disease.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public enum Disease
implements
StatisticsGroupingKey {

AFP(true, true, true, false, false, 0, true, false, false),
AFP(true, true, true, false, true, 60, true, false, false),
CHOLERA(true, true, true, false, true, 5, true, false, false),
CONGENITAL_RUBELLA(true, true, true, false, true, 21, true, false, false),
CSM(true, true, true, false, false, 10, true, false, false),
Expand Down Expand Up @@ -70,9 +70,9 @@ public enum Disease
YAWS_ENDEMIC_SYPHILIS(true, false, false, true, false, 0, true, false, false),
MATERNAL_DEATHS(true, false, false, true, false, 0, true, false, false),
PERINATAL_DEATHS(true, false, false, true, false, 0, true, false, false),
INFLUENZA(false, false, false, false, false, 0, true, false, false),
INFLUENZA_A(true, true, true, false, false, 0, true, false, false),
INFLUENZA_B(true, true, true, false, false, 0, true, false, false),
INFLUENZA(true, false, false, false, false, 0, true, false, false),
INFLUENZA_A(false, true, true, false, false, 0, true, false, false),
INFLUENZA_B(false, true, true, false, false, 0, true, false, false),
H_METAPNEUMOVIRUS(true, false, true, false, false, 0, true, false, false),
RESPIRATORY_SYNCYTIAL_VIRUS(true, false, true, false, false, 0, true, false, false),
PARAINFLUENZA_1_4(true, false, true, false, false, 0, true, false, false),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ public ClassificationExposureCriteriaDto() {
super();
}

public ClassificationExposureCriteriaDto(ExposureType exposureType) {
super();
this.exposureType = exposureType;
}

public ClassificationExposureCriteriaDto(String propertyId, ExposureType exposureType, Object... propertyValues) {

super(propertyId, propertyValues);
Expand All @@ -56,30 +61,35 @@ protected Class<? extends EntityDto> getInvokeClass() {
public boolean eval(CaseDataDto caze, PersonDto person, List<PathogenTestDto> pathogenTests, List<EventDto> events, Date lastVaccinationDate) {

for (ExposureDto exposure : caze.getEpiData().getExposures()) {
if (exposureType != null && exposure.getExposureType() != exposureType) {
continue;
}

Method method;
try {
method = getInvokeClass().getMethod("get" + propertyId.substring(0, 1).toUpperCase() + propertyId.substring(1));
} catch (NoSuchMethodException e) {
// To handle a case, like an exposure type present in the case, we should return true
// This case is to handle the Giardiasis and Cryptosporidiosis diseases where only the exposure available but not its related property.
if (propertyId == null && exposure.getExposureType() == exposureType) {
return true;
} else {
if (exposureType != null && exposure.getExposureType() != exposureType) {
continue;
}
Method method;
try {
method = getInvokeClass().getMethod("is" + propertyId.substring(0, 1).toUpperCase() + propertyId.substring(1));
} catch (NoSuchMethodException newE) {
throw new RuntimeException(newE);
method = getInvokeClass().getMethod("get" + propertyId.substring(0, 1).toUpperCase() + propertyId.substring(1));
} catch (NoSuchMethodException e) {
try {
method = getInvokeClass().getMethod("is" + propertyId.substring(0, 1).toUpperCase() + propertyId.substring(1));
} catch (NoSuchMethodException newE) {
throw new RuntimeException(newE);
}
} catch (SecurityException e) {
throw new RuntimeException(e);
}
Comment on lines +69 to 83
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Potential NullPointerException when both propertyId and exposureType are null.

The code assumes propertyId is non-null when reaching line 74, but this isn't guaranteed. If an instance is created using the default constructor (line 40) or with both fields null, and the exposure has a non-null type, the code will throw a NullPointerException when attempting propertyId.substring(...).

Trace:

  1. Both propertyId and exposureType are null
  2. Line 66: Early return condition fails (if exposure has a type)
  3. Line 69: Filter condition is false (exposureType is null)
  4. Line 74: propertyId.substring(...) → NPE

Consider adding a validation check:

 			} else {
 				if (exposureType != null && exposure.getExposureType() != exposureType) {
 					continue;
 				}
+				if (propertyId == null) {
+					continue; // or throw IllegalStateException
+				}
 				Method method;
 				try {

Alternatively, validate in constructors that at least one of propertyId or exposureType is non-null.

🤖 Prompt for AI Agents
In
sormas-api/src/main/java/de/symeda/sormas/api/caze/classification/ClassificationExposureCriteriaDto.java
around lines 69 to 83, the code uses propertyId.substring(...) without guarding
against propertyId being null which can cause an NPE; fix by adding a null check
before attempting to build the getter name (e.g., if propertyId is null then
skip this reflection block or handle it consistently), or alternatively enforce
via constructors/validation that at least one of propertyId or exposureType is
non-null and throw an IllegalArgumentException early; ensure any added branch
either continues the loop when propertyId is null or throws a clear exception so
substring(...) is never called on a null reference.

} catch (SecurityException e) {
throw new RuntimeException(e);
}

try {
Object value = method.invoke(exposure);
if (propertyValues.contains(value) || CollectionUtils.isEmpty(propertyValues) && YesNoUnknown.YES.equals(value)) {
return true;
try {
Object value = method.invoke(exposure);
if (propertyValues.contains(value) || CollectionUtils.isEmpty(propertyValues) && YesNoUnknown.YES.equals(value)) {
return true;
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException e) {
throw new RuntimeException(e);
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException e) {
throw new RuntimeException(e);
}
}

Expand All @@ -90,9 +100,16 @@ public boolean eval(CaseDataDto caze, PersonDto person, List<PathogenTestDto> pa
public String buildDescription() {

StringBuilder sb = new StringBuilder();
sb.append(I18nProperties.getPrefixCaption(ExposureDto.I18N_PREFIX, propertyId));
if (exposureType != null) {
sb.append(" ").append(I18nProperties.getString(Strings.classificationCriteriaForExposureType)).append(exposureType.toString());
if (propertyId != null) {
sb.append(I18nProperties.getPrefixCaption(ExposureDto.I18N_PREFIX, propertyId));
sb.append(" ").append(I18nProperties.getString(Strings.classificationCriteriaForExposureType)).append(exposureType.toString());
} else {
sb.append(I18nProperties.getString(Strings.classificationCriteriaRestrictedToExposureType))
.append(" ")
.append(exposureType.toString());
}
Comment on lines +104 to +111
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify i18n string keys exist in resource files.

The description logic correctly handles both cases (with and without propertyId). However, please confirm that the following i18n keys are defined in the resource bundles:

  • Strings.classificationCriteriaForExposureType (line 106)
  • Strings.classificationCriteriaRestrictedToExposureType (line 108)

🏁 Script executed:

#!/bin/bash
# Verify the i18n string keys exist in the codebase

echo "Searching for classificationCriteriaForExposureType..."
rg -n "classificationCriteriaForExposureType" --type java --type properties

echo -e "\nSearching for classificationCriteriaRestrictedToExposureType..."
rg -n "classificationCriteriaRestrictedToExposureType" --type java --type properties

Length of output: 189


🏁 Script executed:

#!/bin/bash
# Find properties files and search for the i18n keys

echo "Finding all .properties files..."
fd -e properties

echo -e "\n=== Searching for classificationCriteriaForExposureType ==="
rg -n "classificationCriteriaForExposureType"

echo -e "\n=== Searching for classificationCriteriaRestrictedToExposureType ==="
rg -n "classificationCriteriaRestrictedToExposureType"

echo -e "\n=== Checking Strings enum definitions ==="
rg -n "classificationCriteria" --type java -A 1 -B 1 | head -50

Length of output: 38589


🏁 Script executed:

#!/bin/bash
# Verify classificationCriteriaRestrictedToExposureType exists in all language property files

echo "=== Searching for classificationCriteriaRestrictedToExposureType in language files ==="
rg -c "classificationCriteriaRestrictedToExposureType" sormas-api/src/main/resources/strings*.properties

echo -e "\n=== Total count ==="
rg "classificationCriteriaRestrictedToExposureType" sormas-api/src/main/resources/ | wc -l

echo -e "\n=== Files WITH the key ==="
fd "strings.*properties" sormas-api/src/main/resources/ --exec rg -l "classificationCriteriaRestrictedToExposureType" {} \; | wc -l

Length of output: 190


Add translations for classificationCriteriaRestrictedToExposureType to all language property files.

The verification reveals a critical i18n gap: Strings.classificationCriteriaRestrictedToExposureType is defined only in the base strings.properties file and is missing from all 40+ language-specific translation files (strings_*.properties). While classificationCriteriaForExposureType has proper translations across all locales, the second key used at line 108 will fall back to untranslated text in non-English locales.

Add the key and its translations to each sormas-api/src/main/resources/strings_*.properties file to complete the i18n implementation.

🤖 Prompt for AI Agents
In
sormas-api/src/main/java/de/symeda/sormas/api/caze/classification/ClassificationExposureCriteriaDto.java
around lines 104-111, the i18n key
Strings.classificationCriteriaRestrictedToExposureType used when propertyId is
null exists only in strings.properties and is missing from all language-specific
files; add the key classificationCriteriaRestrictedToExposureType with
appropriate translated values to every
sormas-api/src/main/resources/strings_*.properties file (one entry per file),
using the same phrasing and placeholder semantics as
classificationCriteriaForExposureType translations to ensure consistent
localized output across all locales.


}

return sb.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ public class HealthConditionsDto extends PseudonymizableDto {
public static final String PREVIOUS_TUBERCULOSIS_TREATMENT = "previousTuberculosisTreatment";
public static final String COMPLIANCE_WITH_TREATMENT = "complianceWithTreatment";
public static final String RECURRENT_BRONCHIOLITIS = "recurrentBronchiolitis";
public static final String IMMUNODEPRESSION = "immunodepression";

@HideForCountries(countries = {
CountryHelper.COUNTRY_CODE_GERMANY,
Expand Down Expand Up @@ -146,10 +145,6 @@ public class HealthConditionsDto extends PseudonymizableDto {
Disease.RESPIRATORY_SYNCYTIAL_VIRUS })
private YesNoUnknown recurrentBronchiolitis;

@Diseases(value = {
Disease.RESPIRATORY_SYNCYTIAL_VIRUS })
private YesNoUnknown immunodepression;

public static HealthConditionsDto build() {
HealthConditionsDto healthConditions = new HealthConditionsDto();
healthConditions.setUuid(DataHelper.createUuid());
Expand Down Expand Up @@ -395,12 +390,4 @@ public YesNoUnknown getRecurrentBronchiolitis() {
public void setRecurrentBronchiolitis(YesNoUnknown recurrentBronchiolitis) {
this.recurrentBronchiolitis = recurrentBronchiolitis;
}

public YesNoUnknown getImmunodepression() {
return immunodepression;
}

public void setImmunodepression(YesNoUnknown immunodepression) {
this.immunodepression = immunodepression;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ public class ExposureDto extends PseudonymizableDto {
public static final String SWIMMING_LOCATION = "swimmingLocation";
public static final String SWIMMING_LOCATION_TYPE = "swimmingLocationType";
public static final String ANIMAL_LOCATION = "animalLocation";
public static final String ANIMAL_LOCATION_TEXT = "animalLocationText";
public static final String DOMESTIC_SWIMMING = "domesticSwimming";
public static final String INTERNATIONAL_SWIMMING = "internationalSwimming";
public static final String SEXUAL_EXPOSURE_TEXT = "sexualExposureText";
Expand Down Expand Up @@ -271,6 +272,11 @@ public class ExposureDto extends PseudonymizableDto {
Disease.GIARDIASIS,
Disease.CRYPTOSPORIDIOSIS })
private AnimalLocation animalLocation;
@Diseases({
Disease.GIARDIASIS,
Disease.CRYPTOSPORIDIOSIS })
@Size(max = FieldConstraints.CHARACTER_LIMIT_TEXT, message = Validations.textTooLong)
private String animalLocationText;
Comment thread
KarnaiahPesula marked this conversation as resolved.
@Diseases({
Disease.AFP,
Disease.CHOLERA,
Expand Down Expand Up @@ -853,6 +859,14 @@ public void setAnimalLocation(AnimalLocation animalLocation) {
this.animalLocation = animalLocation;
}

public String getAnimalLocationText() {
return animalLocationText;
}

public void setAnimalLocationText(String animalLocationText) {
this.animalLocationText = animalLocationText;
}

public TravelAccommodation getTravelAccommodation() {
return travelAccommodation;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1807,6 +1807,7 @@ public interface Captions {
String Exposure_animalContactType = "Exposure.animalContactType";
String Exposure_animalContactTypeDetails = "Exposure.animalContactTypeDetails";
String Exposure_animalLocation = "Exposure.animalLocation";
String Exposure_animalLocationText = "Exposure.animalLocationText";
String Exposure_animalMarket = "Exposure.animalMarket";
String Exposure_animalVaccinated = "Exposure.animalVaccinated";
String Exposure_bodyOfWater = "Exposure.bodyOfWater";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public interface Strings {
String classificationConfirmedUnknownSymptoms = "classificationConfirmedUnknownSymptoms";
String classificationCriteriaForExposureType = "classificationCriteriaForExposureType";
String classificationCriteriaForTestType = "classificationCriteriaForTestType";
String classificationCriteriaRestrictedToExposureType = "classificationCriteriaRestrictedToExposureType";
String classificationDaysBeforeCaseStart = "classificationDaysBeforeCaseStart";
String classificationEventCluster = "classificationEventCluster";
String classificationForDisease = "classificationForDisease";
Expand Down Expand Up @@ -423,6 +424,7 @@ public interface Strings {
String forContact = "forContact";
String forEnvironment = "forEnvironment";
String forEventParticipant = "forEventParticipant";
String giardiaInfoExposureInvestigation = "giardiaInfoExposureInvestigation";
String headingAccessDenied = "headingAccessDenied";
String headingActivityAsCase = "headingActivityAsCase";
String headingActivityAsCaseDetails = "headingActivityAsCaseDetails";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,29 +218,35 @@ public class PersonDto extends PseudonymizableDto implements IsPerson {
@Outbreaks
private Date approximateAgeReferenceDate;
@Diseases({
Disease.CONGENITAL_RUBELLA })
Disease.CONGENITAL_RUBELLA,
Disease.RESPIRATORY_SYNCYTIAL_VIRUS })
@HideForCountries
private RegionReferenceDto placeOfBirthRegion;
@Diseases({
Disease.CONGENITAL_RUBELLA })
Disease.CONGENITAL_RUBELLA,
Disease.RESPIRATORY_SYNCYTIAL_VIRUS })
@HideForCountries
private DistrictReferenceDto placeOfBirthDistrict;
@Diseases({
Disease.CONGENITAL_RUBELLA })
Disease.CONGENITAL_RUBELLA,
Disease.RESPIRATORY_SYNCYTIAL_VIRUS })
@HideForCountries
@SensitiveData
private CommunityReferenceDto placeOfBirthCommunity;
@Diseases({
Disease.CONGENITAL_RUBELLA })
Disease.CONGENITAL_RUBELLA,
Disease.RESPIRATORY_SYNCYTIAL_VIRUS })
@HideForCountries
private FacilityType placeOfBirthFacilityType;
@Diseases({
Disease.CONGENITAL_RUBELLA })
Disease.CONGENITAL_RUBELLA,
Disease.RESPIRATORY_SYNCYTIAL_VIRUS })
@HideForCountries
@SensitiveData
private FacilityReferenceDto placeOfBirthFacility;
@Diseases({
Disease.CONGENITAL_RUBELLA })
Disease.CONGENITAL_RUBELLA,
Disease.RESPIRATORY_SYNCYTIAL_VIRUS })
@HideForCountries
@SensitiveData
@Size(max = FieldConstraints.CHARACTER_LIMIT_DEFAULT, message = Validations.textTooLong)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2218,6 +2218,7 @@ public static SymptomsDto build() {
@HideForCountries(countries = {
CountryHelper.COUNTRY_CODE_GERMANY,
CountryHelper.COUNTRY_CODE_SWITZERLAND })
@SymptomGrouping(SymptomGroup.RESPIRATORY)
private SymptomState wheezing;

@Diseases({
Expand Down Expand Up @@ -2609,7 +2610,8 @@ public static SymptomsDto build() {
PERTUSSIS,
MEASLES,
GIARDIASIS,
CRYPTOSPORIDIOSIS })
CRYPTOSPORIDIOSIS,
RESPIRATORY_SYNCYTIAL_VIRUS })
private SymptomState asymptomatic;
@Diseases({
INVASIVE_MENINGOCOCCAL_INFECTION })
Expand Down Expand Up @@ -2675,8 +2677,7 @@ public static SymptomsDto build() {
GIARDIASIS,
CRYPTOSPORIDIOSIS })
@DependantOn("parentTimeOffWork")
@Size(max = 50, message = Validations.textTooLong)
private String timeOffWorkDays;
private Float timeOffWorkDays;

@HideForCountriesExcept(countries = CountryHelper.COUNTRY_CODE_LUXEMBOURG)
@Diseases({
Expand Down Expand Up @@ -4540,11 +4541,11 @@ public void setParentTimeOffWork(YesNoUnknown parentTimeOffWork) {
this.parentTimeOffWork = parentTimeOffWork;
}

public String getTimeOffWorkDays() {
public Float getTimeOffWorkDays() {
return timeOffWorkDays;
}

public void setTimeOffWorkDays(String timeOffWorkDays) {
public void setTimeOffWorkDays(Float timeOffWorkDays) {
this.timeOffWorkDays = timeOffWorkDays;
}

Expand Down
3 changes: 2 additions & 1 deletion sormas-api/src/main/resources/captions.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1577,7 +1577,8 @@ Exposure.domesticSwimming=Swimming in Luxembourg
Exposure.internationalSwimming=Swimming abroad
Exposure.swimmingLocation=Swimming Location
Exposure.swimmingLocationType=Specify swimming location
Exposure.animalLocation= Animal Location
Exposure.animalLocation= Animal location
Exposure.animalLocationText= Specify animal location
Exposure.sexualExposureText= Specify sexual exposure

Exposure.rawFoodContact= Contact with raw pet food
Expand Down
2 changes: 1 addition & 1 deletion sormas-api/src/main/resources/enum.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2440,7 +2440,7 @@ MedicallyAssociatedTransmissionMode.INJECTION_FOR_MEDICAL_PURPOSES=Injection for

# MultipleBirth
MultipleBirth.SINGLE=Single birth (Singleton - 1)
MultipleBirth.TWIN=Twin birth (Twins - 2)
MultipleBirth.TWINS=Twin birth (Twins - 2)
MultipleBirth.MULTIPLE=Multiple birth (Triplet 3+ or more)

# ExternalShareDateType
Expand Down
2 changes: 2 additions & 0 deletions sormas-api/src/main/resources/strings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ classificationConfirmedNoSymptoms = Confirmed Classification - No symptoms
classificationConfirmedUnknownSymptoms = Confirmed Classification - Unknown symptoms
classificationCriteriaForTestType = for test type
classificationCriteriaForExposureType = for exposure type
classificationCriteriaRestrictedToExposureType = Exposure to
classificationDaysBeforeCaseStart = days before symptom onset/case report date
classificationEventCluster = Case linked to a cluster event
classificationForDisease = for
Expand Down Expand Up @@ -1110,6 +1111,7 @@ populationDataByRegion = Population data by Region
populationDataByCommunity = No population data available for communities
populationDataByDistrict = Population data by District
infoExposureInvestigation = <i>Please document ALL relevant direct exposures (e.g. attended gatherings, travels, animal contacts, etc.) during the incubation period:</i>
giardiaInfoExposureInvestigation = <i>Please consider 25 days before the onset of the symptoms</i>
infoExposureInvestigationContacts = <i>Please document information about the exposure that led to this contact:</i>
infoEpiDataFieldsHint = <i>Please indicate if any of the following is relevant for the patient during the incubation period:</i>
infoEpiDataSourceCaseContacts = <i>Please indicate ALL contacts with potential source cases during the incubation period:</i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,6 @@ private void buildCriteria() {
addCriteria(Disease.PERTUSSIS, DateHelper.getDateZero(2020, 11, 6), suspect, probable, confirmed, null);

// Giardiasis
// FIXME: Check the case classification exposure criteria for giardiasis, its is wrong for now
probable = allOf(
xOf(
1,
Expand All @@ -542,28 +541,34 @@ private void buildCriteria() {
symptom(SymptomsDto.WEIGHT_LOSS)),
xOf(
1,
oneOfCompact(epiData(EpiDataDto.CONTACT_WITH_SOURCE_CASE_KNOWN), exposure(ExposureDto.EXPOSURE_TYPE, ExposureType.ANIMAL_CONTACT)),
oneOfCompact(
epiData(EpiDataDto.CONTACT_WITH_SOURCE_CASE_KNOWN),
exposure(ExposureDto.EXPOSURE_TYPE, ExposureType.RECREATIONAL_WATER)),
oneOfCompact(epiData(EpiDataDto.CONTACT_WITH_SOURCE_CASE_KNOWN), exposure(ExposureDto.EXPOSURE_TYPE, ExposureType.FOOD)),
oneOfCompact(epiData(EpiDataDto.CONTACT_WITH_SOURCE_CASE_KNOWN), exposure(ExposureDto.EXPOSURE_TYPE, ExposureType.FLOOD_EXPOSURE)),
oneOfCompact(epiData(EpiDataDto.CONTACT_WITH_SOURCE_CASE_KNOWN), exposure(ExposureDto.EXPOSURE_TYPE, ExposureType.SEXUAL_CONTACT))));
exposure(ExposureType.ANIMAL_CONTACT),
exposure(ExposureType.RECREATIONAL_WATER),
exposure(ExposureType.FOOD),
exposure(ExposureType.FLOOD_EXPOSURE),
exposure(ExposureType.SEXUAL_CONTACT)));
confirmed = allOf(
xOf(
1,
symptom(SymptomsDto.DIARRHEA),
symptom(SymptomsDto.BLOATING),
symptom(SymptomsDto.ABDOMINAL_PAIN),
symptom(SymptomsDto.WEIGHT_LOSS)),
xOf(1, (positiveTestResult(Disease.GIARDIASIS, PathogenTestType.MICROSCOPY, PathogenTestType.PCR_RT_PCR, PathogenTestType.CULTURE))));
addCriteria(Disease.GIARDIASIS, DateHelper.getDateZero(2020, 11, 6), null, probable, confirmed, null);

// Cryptosporidiosis
// FIXME: Check the case classification exposure criteria for cryptosporidiosis, its is wrong for now
probable = allOf(
caseData(CaseDataDto.EPIDEMIOLOGICAL_CONFIRMATION, YesNoUnknown.YES),
xOf(1, symptom(SymptomsDto.DIARRHEA), symptom(SymptomsDto.ABDOMINAL_PAIN)),
xOf(
1,
exposure(ExposureDto.RAW_FOOD_CONTACT, ExposureType.FOOD),
exposure(ExposureDto.SYMPTOMATIC_INDIVIDUAL_TEXT, ExposureType.SYMPTOMATIC_CONTACT),
exposure(ExposureDto.SEXUAL_EXPOSURE_TEXT, ExposureType.SEXUAL_CONTACT)));
exposure(ExposureType.FOOD),
exposure(ExposureType.RECREATIONAL_WATER),
exposure(ExposureType.SEXUAL_CONTACT),
exposure(ExposureType.FLOOD_EXPOSURE),
exposure(ExposureType.SYMPTOMATIC_CONTACT),
exposure(ExposureType.ANIMAL_CONTACT)));
confirmed = allOf(
xOf(1, symptom(SymptomsDto.DIARRHEA), symptom(SymptomsDto.ABDOMINAL_PAIN)),
xOf(
1,
(positiveTestResult(Disease.CRYPTOSPORIDIOSIS, PathogenTestType.MICROSCOPY, PathogenTestType.PCR_RT_PCR, PathogenTestType.CULTURE))));
Expand Down Expand Up @@ -723,6 +728,10 @@ private ClassificationEpiDataCriteriaDto epiData(String propertyId) {
return new ClassificationEpiDataCriteriaDto(propertyId);
}

private ClassificationExposureCriteriaDto exposure(ExposureType exposureType) {
return new ClassificationExposureCriteriaDto(exposureType);
}

private ClassificationExposureCriteriaDto exposure(String propertyId, ExposureType exposureType, Object... propertyValues) {
return new ClassificationExposureCriteriaDto(propertyId, exposureType, propertyValues);
}
Expand Down
Loading
Loading