Skip to content

Commit 269e845

Browse files
committed
♻️ Cleanup before trying to refactor data patcher to be similar to retriever
1 parent 76f5480 commit 269e845

5 files changed

Lines changed: 87 additions & 18 deletions

File tree

sormas-backend/src/main/java/de/symeda/sormas/backend/patch/BusinessDtoFacade.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.util.Map;
77
import java.util.Optional;
88
import java.util.Set;
9+
import java.util.function.BiFunction;
910
import java.util.function.Function;
1011
import java.util.stream.Collectors;
1112

@@ -44,6 +45,7 @@ public class BusinessDtoFacade {
4445
private UserFacadeEjb.UserFacadeEjbLocal userFacade;
4546

4647
private final Map<Class<? extends EntityDto>, Function<? extends EntityDto, ? extends EntityDto>> directDtoSaveDictionary = new HashMap<>();
48+
private final Map<Class<? extends EntityDto>, BiFunction<CaseDataDto, ? extends EntityDto, ? extends EntityDto>> saveFromCaseDictionary = new HashMap<>();
4749

4850
private final Map<Class<? extends EntityDto>, Function<CaseDataDto, ? extends EntityDto>> dtoRetrieverDictionary = new HashMap<>();
4951

@@ -209,11 +211,12 @@ public Set<String> fetchablePrefixes() {
209211
* @param <T>
210212
* type
211213
*/
214+
212215
public <T extends EntityDto> T save(@NotNull EntityDto entityDto) {
213216
Class<? extends EntityDto> entityDtoClass = entityDto.getClass();
214217

215218
return Optional.ofNullable((Function<T, T>) directDtoSaveDictionary.get(entityDtoClass))
216-
.orElseThrow(() -> new IllegalStateException(String.format("No save function defined for: [%s]", entityDtoClass)))
217-
.apply((T) entityDto);
219+
.orElseThrow(() -> new IllegalStateException(String.format("No save function defined for: [%s]", entityDtoClass)))
220+
.apply((T) entityDto);
218221
}
219222
}

sormas-backend/src/main/java/de/symeda/sormas/backend/patch/alias/PathAliasHelper.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,12 @@ public class PathAliasHelper {
5959
"Location",
6060
Set.of(toFieldName(PersonDto.I18N_PREFIX, PersonDto.ADDRESS), toFieldName(ExposureDto.I18N_PREFIX, ExposureDto.LOCATION)));
6161

62+
/**
63+
* Meant for fields that are only references from another entity.
64+
*/
6265
public static final Map<String, String> REFERENCE_TO_ROOT_DICTIONARY = Map.of(
6366
toFieldName(CaseDataDto.I18N_PREFIX, CaseDataDto.PERSON),
64-
PersonDto.I18N_PREFIX,
65-
toFieldName(CaseDataDto.I18N_PREFIX, CaseDataDto.EPI_DATA),
66-
EpiDataDto.I18N_PREFIX);
67+
PersonDto.I18N_PREFIX);
6768

6869
private static @NotNull HashMap<String, String> buildDefaultAliasDictionary() {
6970
HashMap<String, String> dictionary = new HashMap<>();
@@ -84,10 +85,10 @@ public class PathAliasHelper {
8485
dictionary.put(SubcontinentDto.I18N_PREFIX, toFieldName(toFieldName(PersonDto.I18N_PREFIX, PersonDto.ADDRESS), LocationDto.SUB_CONTINENT));
8586
dictionary.put(ContinentDto.I18N_PREFIX, toFieldName(toFieldName(PersonDto.I18N_PREFIX, PersonDto.ADDRESS), LocationDto.CONTINENT));
8687
dictionary.put(UserDto.I18N_PREFIX, toFieldName(CaseDataDto.I18N_PREFIX, CaseDataDto.FOLLOW_UP_STATUS_CHANGE_USER));
88+
8789
dictionary.put(EpiDataDto.I18N_PREFIX, toFieldName(CaseDataDto.I18N_PREFIX, CaseDataDto.EPI_DATA));
88-
// TODO: check if required
89-
// dictionary.put(ExposureDto.I18N_PREFIX, toFieldName(CaseDataDto.I18N_PREFIX, CaseDataDto.EPI_DATA));
90-
// dictionary.put(ActivityAsCaseDto.I18N_PREFIX, toFieldName(CaseDataDto.I18N_PREFIX, CaseDataDto.EPI_DATA));
90+
dictionary.put(ExposureDto.I18N_PREFIX, toFieldName(toFieldName(CaseDataDto.I18N_PREFIX, CaseDataDto.EPI_DATA), EpiDataDto.EXPOSURES));
91+
dictionary.put(ActivityAsCaseDto.I18N_PREFIX, toFieldName(toFieldName(CaseDataDto.I18N_PREFIX, CaseDataDto.EPI_DATA), EpiDataDto.ACTIVITIES_AS_CASE));
9192

9293
return dictionary;
9394
}

sormas-backend/src/main/java/de/symeda/sormas/backend/patch/partial_retrieval/PartialRetrieverImpl.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ private Tuple<String, Tuple<FieldInfo, PartialRetrievalFailureCause>> buildTuple
9999
.orElse(null);
100100

101101
if (failureCause != null) {
102-
return Tuple.of(originalFieldName, new Tuple<>((FieldInfo) null, failureCause));
102+
return Tuple.of(originalFieldName, new Tuple<>(null, failureCause));
103103
}
104104

105105
String pathWithoutAlias = unAliasedTuple.getFirst();
@@ -109,22 +109,22 @@ private Tuple<String, Tuple<FieldInfo, PartialRetrievalFailureCause>> buildTuple
109109
Optional<EntityDto> adequateBeanOpt = getAdequateBean(pathWithoutAlias, caseData, beanCache);
110110

111111
if (adequateBeanOpt.isEmpty()) {
112-
return Tuple.of(originalFieldName, new Tuple<>((FieldInfo) null, PartialRetrievalFailureCause.ENTITY_COULD_NOT_BE_FOUND));
112+
return Tuple.of(originalFieldName, new Tuple<>(null, PartialRetrievalFailureCause.ENTITY_COULD_NOT_BE_FOUND));
113113
}
114114

115115
EntityDto adequateBean = adequateBeanOpt.orElseThrow();
116116
Optional<FieldInfo> specificFieldInfo = specificFieldValueRetrieverRegistry.getFieldInfo(aliasPath, adequateBean);
117117

118118
if (specificFieldInfo.isPresent()) {
119-
return Tuple.of(originalFieldName, new Tuple<>(specificFieldInfo.get(), (PartialRetrievalFailureCause) null));
119+
return Tuple.of(originalFieldName, new Tuple<>(specificFieldInfo.get(), null));
120120
}
121121

122-
Tuple<Tuple<Class<?>, Object>, PropertyAccessFailure> propertyType =
122+
@NotNull Tuple<Tuple<Class<?>, Object>, PropertyAccessFailure> propertyType =
123123
PropertyAccessor.getPropertyTypeAndValue(adequateBean, physicalPathName, getFieldVisibilityCheckers(caseData.getDisease()));
124124

125125
PropertyAccessFailure propertyAccessFailure = propertyType.getSecond();
126126
if (propertyAccessFailure != null) {
127-
return Tuple.of(originalFieldName, new Tuple<>((FieldInfo) null, propertyAccessFailure.getRelatedRetrieveFailureCause()));
127+
return Tuple.of(originalFieldName, new Tuple<>(null, propertyAccessFailure.getRelatedRetrieveFailureCause()));
128128
}
129129

130130
Tuple<Class<?>, Object> fieldInfo = propertyType.getFirst();
@@ -140,7 +140,7 @@ private Tuple<String, Tuple<FieldInfo, PartialRetrievalFailureCause>> buildTuple
140140
originalFieldName,
141141
new Tuple<>(
142142
new FieldInfo().setFieldType(fieldInfo.getFirst()).setFieldValue(fieldInfo.getSecond()).setTranslatedFieldName(translatedFieldName),
143-
(PartialRetrievalFailureCause) null));
143+
null));
144144
}
145145

146146
@Override
@@ -161,13 +161,13 @@ public DisplayablePartialRetrievalResponse retrievePartialForDisplay(PartialRetr
161161
}
162162

163163
private Optional<EntityDto> getAdequateBean(
164-
@NotNull String path,
164+
@NotNull String pathWithoutAlias,
165165
@NotNull CaseDataDto caseData,
166166
@NotNull Map<String, Optional<EntityDto>> beanCache) {
167167

168-
int i = path.indexOf(".");
168+
int i = pathWithoutAlias.indexOf(".");
169169

170-
String prefix = StringUtils.substring(path, 0, i);
170+
String prefix = StringUtils.substring(pathWithoutAlias, 0, i);
171171

172172
if (CaseDataDto.I18N_PREFIX.equals(prefix)) {
173173
return Optional.of(caseData);
@@ -182,7 +182,7 @@ private Optional<EntityDto> getAdequateBean(
182182
}
183183

184184
if (entitiesSize != 1) {
185-
logger.warn("Only first element is supported for now: [{}], was: [{}]", path, entitiesSize);
185+
logger.warn("Only first element is supported for now: [{}], was: [{}]", pathWithoutAlias, entitiesSize);
186186
}
187187

188188
return Optional.ofNullable(entityDtos).map(actualEntities -> actualEntities.get(0));

sormas-backend/src/test/java/de/symeda/sormas/backend/patch/partial_retrieval/PartialRetrieverImplTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import de.symeda.sormas.api.Language;
1111
import de.symeda.sormas.api.caze.CaseDataDto;
1212
import de.symeda.sormas.api.caze.Vaccine;
13+
import de.symeda.sormas.api.epidata.EpiDataDto;
14+
import de.symeda.sormas.api.utils.YesNoUnknown;
1315
import de.symeda.sormas.api.i18n.I18nProperties;
1416
import de.symeda.sormas.api.immunization.ImmunizationDto;
1517
import de.symeda.sormas.api.immunization.ImmunizationStatus;
@@ -253,6 +255,39 @@ void retrieve_contact_details_email() {
253255
() -> Assertions.assertEquals("mail@mail.ch", personFirstNameFieldInfo.getFieldValue()));
254256
}
255257

258+
@Test
259+
void retrievePartial_epiData_twoFields() {
260+
// PREPARE
261+
Disease disease = Disease.PERTUSSIS;
262+
CaseDataDto originalCase = creator.createUnclassifiedCase(disease);
263+
264+
originalCase.getEpiData().setExposureDetailsKnown(YesNoUnknown.YES);
265+
originalCase.getEpiData().setContactWithSourceCaseKnown(YesNoUnknown.NO);
266+
getCaseFacade().save(originalCase);
267+
268+
String exposureDetailsKnownFieldName = toFieldName(EpiDataDto.I18N_PREFIX, EpiDataDto.EXPOSURE_DETAILS_KNOWN);
269+
String contactWithSourceCaseKnownFieldName = toFieldName(EpiDataDto.I18N_PREFIX, EpiDataDto.CONTACT_WITH_SOURCE_CASE_KNOWN);
270+
271+
// EXECUTE
272+
PartialRetrievalResponse actual = victim().retrievePartial(
273+
new PartialRetrievalRequest().setCaseUuid(originalCase.getUuid())
274+
.setFieldsToRetrieve(Set.of(exposureDetailsKnownFieldName, contactWithSourceCaseKnownFieldName)));
275+
276+
// CHECK
277+
FieldInfo exposureDetailsKnownFieldInfo = actual.getFieldInfoDictionary().get(exposureDetailsKnownFieldName);
278+
FieldInfo contactWithSourceCaseKnownFieldInfo = actual.getFieldInfoDictionary().get(contactWithSourceCaseKnownFieldName);
279+
Assertions.assertAll(
280+
() -> Assertions.assertTrue(actual.getFailuresDictionary().isEmpty()),
281+
282+
() -> Assertions.assertTrue(actual.getFieldInfoDictionary().containsKey(exposureDetailsKnownFieldName)),
283+
() -> Assertions.assertEquals("Exposure details known", exposureDetailsKnownFieldInfo.getTranslatedFieldName()),
284+
() -> Assertions.assertEquals(YesNoUnknown.YES, exposureDetailsKnownFieldInfo.getFieldValue()),
285+
286+
() -> Assertions.assertTrue(actual.getFieldInfoDictionary().containsKey(contactWithSourceCaseKnownFieldName)),
287+
() -> Assertions.assertEquals("Contacts with source case known", contactWithSourceCaseKnownFieldInfo.getTranslatedFieldName()),
288+
() -> Assertions.assertEquals(YesNoUnknown.NO, contactWithSourceCaseKnownFieldInfo.getFieldValue()));
289+
}
290+
256291
private static String toFieldName(String prefix, String fieldName) {
257292
return prefix + '.' + fieldName;
258293
}

sormas-backend/src/test/java/de/symeda/sormas/patch/DataPatcherImplTest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import de.symeda.sormas.api.patch.*;
3737
import de.symeda.sormas.api.person.*;
3838
import de.symeda.sormas.api.symptoms.SymptomState;
39+
import de.symeda.sormas.api.utils.YesNoUnknown;
3940
import de.symeda.sormas.api.vaccination.VaccinationDto;
4041
import de.symeda.sormas.backend.AbstractBeanTest;
4142
import de.symeda.sormas.backend.MockProducer;
@@ -942,6 +943,35 @@ void patch_fieldDoesNoExist() {
942943
() -> Assertions.assertEquals(Map.of(), response.getValidPatchDictionary()));
943944
}
944945

946+
@Test
947+
void patch_epiData() {
948+
// PREPARE
949+
CaseDataDto originalCase = creator.createUnclassifiedCase(Disease.PERTUSSIS);
950+
951+
CaseDataPatchRequest request = new CaseDataPatchRequest().setCaseUuid(originalCase.getUuid())
952+
.setReplacementStrategy(DataReplacementStrategy.ALWAYS)
953+
.setPatchDictionary(
954+
Map.of(
955+
"EpiData.exposureDetailsKnown",
956+
"YES",
957+
958+
"EpiData.contactWithSourceCaseKnown",
959+
"NO"));
960+
961+
// EXECUTE
962+
DataPatchResponse response = victim().patch(request);
963+
964+
// CHECK
965+
logger.info("response: [{}]", response);
966+
967+
CaseDataDto actualCase = getCaseFacade().getByUuid(originalCase.getUuid());
968+
969+
Assertions.assertAll(
970+
() -> Assertions.assertTrue(response.getFailures().isEmpty(), "Failure found, but should be empty"),
971+
() -> Assertions.assertEquals(YesNoUnknown.YES, actualCase.getEpiData().getExposureDetailsKnown()),
972+
() -> Assertions.assertEquals(YesNoUnknown.NO, actualCase.getEpiData().getContactWithSourceCaseKnown()));
973+
}
974+
945975
@Test
946976
void patch_ifNotAlreadyPresent_sameDayDifferentTime_noForbiddenValueOverride() {
947977
// PREPARE

0 commit comments

Comments
 (0)