Skip to content

Commit 9adb400

Browse files
committed
✨ [Untested] grouped patching is now possible as new entities are generated from businessDtoFacade.
1 parent a56f07a commit 9adb400

16 files changed

Lines changed: 390 additions & 212 deletions

File tree

sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/ExternalMessageFacade.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import java.util.Date;
44
import java.util.List;
5-
import java.util.Map;
65

76
import javax.annotation.Nullable;
87
import javax.ejb.Remote;
@@ -13,6 +12,7 @@
1312
import de.symeda.sormas.api.ReferenceDto;
1413
import de.symeda.sormas.api.caze.surveillancereport.SurveillanceReportReferenceDto;
1514
import de.symeda.sormas.api.common.Page;
15+
import de.symeda.sormas.api.externalmessage.survey.PatchDictionary;
1616
import de.symeda.sormas.api.patch.partial_retrieval.DisplayablePartialRetrievalResponse;
1717
import de.symeda.sormas.api.sample.SampleReferenceDto;
1818
import de.symeda.sormas.api.user.UserReferenceDto;
@@ -96,7 +96,7 @@ default List<ExternalMessageDto> saveAndProcessSurveyResponses() {
9696
* the corrected field path -> value map to apply
9797
* @return updated ExternalMessageDto after reprocessing
9898
*/
99-
ExternalMessageDto overwriteSurveyResponse(String uuid, Map<String, Object> correctedDictionary);
99+
ExternalMessageDto overwriteSurveyResponse(String uuid, PatchDictionary correctedDictionary);
100100

101101
/**
102102
* Retrieves display-ready field information (translated names and current case values) for all fields

sormas-api/src/main/java/de/symeda/sormas/api/externalmessage/survey/ExternalMessageSurveyResponseRequest.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import java.io.Serializable;
44
import java.util.Date;
5-
import java.util.LinkedHashMap;
65
import java.util.List;
76
import java.util.Objects;
87

@@ -43,14 +42,14 @@ public class ExternalMessageSurveyResponseRequest implements Serializable, Compa
4342
* The accepted fields are those from {@link InfoFacade#generateDataDictionary()}.
4443
*/
4544
@NotNull
46-
private LinkedHashMap<String, Object> patchDictionary;
45+
private PatchDictionary patchDictionary = new PatchDictionary();
4746

4847
/**
4948
* Contains fields that were excluded from the patch dictionary, meant for fields that may not start with the prefix.
5049
* The prefix allows to safely exclude fields that are not meant to be mapped into SORMAS.
5150
*/
5251
@NotNull
53-
private LinkedHashMap<String, Object> excludedPatchDictionary;
52+
private PatchDictionary excludedPatchDictionary = new PatchDictionary();
5453

5554
/**
5655
* Origin that wants the patch operation.
@@ -140,11 +139,11 @@ public ExternalMessageSurveyResponseRequest setEmptyValueBehavior(EmptyValueBeha
140139
return this;
141140
}
142141

143-
public LinkedHashMap<String, Object> getPatchDictionary() {
142+
public PatchDictionary getPatchDictionary() {
144143
return patchDictionary;
145144
}
146145

147-
public ExternalMessageSurveyResponseRequest setPatchDictionary(LinkedHashMap<String, Object> patchDictionary) {
146+
public ExternalMessageSurveyResponseRequest setPatchDictionary(PatchDictionary patchDictionary) {
148147
this.patchDictionary = patchDictionary;
149148
return this;
150149
}
@@ -187,11 +186,11 @@ public ExternalMessageSurveyResponseRequest setSkipIfAlreadyProcessed(boolean sk
187186
return this;
188187
}
189188

190-
public LinkedHashMap<String, Object> getExcludedPatchDictionary() {
189+
public PatchDictionary getExcludedPatchDictionary() {
191190
return excludedPatchDictionary;
192191
}
193192

194-
public ExternalMessageSurveyResponseRequest setExcludedPatchDictionary(LinkedHashMap<String, Object> excludedPatchDictionary) {
193+
public ExternalMessageSurveyResponseRequest setExcludedPatchDictionary(PatchDictionary excludedPatchDictionary) {
195194
this.excludedPatchDictionary = excludedPatchDictionary;
196195
return this;
197196
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package de.symeda.sormas.api.externalmessage.survey;
2+
3+
import java.io.Serializable;
4+
import java.util.LinkedHashMap;
5+
import java.util.Map;
6+
import java.util.Objects;
7+
8+
import javax.validation.constraints.NotNull;
9+
10+
/**
11+
* Wrapper around concrete storage for patch dictionary.
12+
*/
13+
public class PatchDictionary implements Serializable {
14+
15+
@NotNull
16+
private LinkedHashMap<PatchField, Object> dictionary = new LinkedHashMap<>();
17+
18+
/**
19+
* Helper method when you don't have any grouped fields.
20+
*
21+
* @param key
22+
* {@link PatchField#getField()}
23+
* @param value
24+
* value within dictionary
25+
*/
26+
public void put(String key, Object value) {
27+
dictionary.put(new PatchField().setField(key), value);
28+
}
29+
30+
public void put(PatchField key, Object value) {
31+
dictionary.put(key, value);
32+
}
33+
34+
public LinkedHashMap<PatchField, Object> getDictionary() {
35+
return dictionary;
36+
}
37+
38+
public PatchDictionary setDictionary(LinkedHashMap<PatchField, Object> dictionary) {
39+
this.dictionary = dictionary;
40+
return this;
41+
}
42+
43+
public PatchDictionary setNonTypedPatchDictionary(Map<PatchField, Object> patchDictionary) {
44+
this.dictionary = new LinkedHashMap<>(patchDictionary);
45+
return this;
46+
}
47+
48+
public boolean isEmpty() {
49+
return dictionary.isEmpty();
50+
}
51+
52+
@Override
53+
public boolean equals(Object o) {
54+
if (o == null || getClass() != o.getClass())
55+
return false;
56+
PatchDictionary that = (PatchDictionary) o;
57+
return Objects.equals(dictionary, that.dictionary);
58+
}
59+
60+
@Override
61+
public int hashCode() {
62+
return Objects.hashCode(dictionary);
63+
}
64+
65+
@Override
66+
public String toString() {
67+
return "PatchDictionary{" + "dictionary=" + dictionary + '}';
68+
}
69+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package de.symeda.sormas.api.externalmessage.survey;
2+
3+
import java.io.Serializable;
4+
import java.util.Objects;
5+
import java.util.Optional;
6+
7+
import javax.annotation.Nullable;
8+
import javax.validation.constraints.NotNull;
9+
10+
/**
11+
* To be able to repeat some groups and make them belong together, the groupIndex was added.
12+
*/
13+
public class PatchField implements Serializable {
14+
15+
private static final long serialVersionUID = 1L;
16+
17+
@NotNull
18+
private String field;
19+
20+
/**
21+
* 0-based index of belonging within the repeated occurrence.
22+
*/
23+
@Nullable
24+
private Integer groupIndex;
25+
26+
public static PatchField of(String field, Integer groupIndex) {
27+
return new PatchField().setField(field).setGroupIndex(groupIndex);
28+
}
29+
30+
public static PatchField of(String field) {
31+
return new PatchField().setField(field);
32+
}
33+
34+
public String getField() {
35+
return field;
36+
}
37+
38+
public PatchField setField(String field) {
39+
this.field = field;
40+
return this;
41+
}
42+
43+
@Nullable
44+
public Integer getGroupIndex() {
45+
return groupIndex;
46+
}
47+
48+
public PatchField setGroupIndex(@Nullable Integer groupIndex) {
49+
this.groupIndex = groupIndex;
50+
return this;
51+
}
52+
53+
public Optional<Integer> getGroupNumber() {
54+
return Optional.ofNullable(groupIndex).map(index -> index + 1);
55+
}
56+
57+
@Override
58+
public boolean equals(Object o) {
59+
if (o == null || getClass() != o.getClass())
60+
return false;
61+
PatchField that = (PatchField) o;
62+
return Objects.equals(field, that.field) && Objects.equals(groupIndex, that.groupIndex);
63+
}
64+
65+
@Override
66+
public int hashCode() {
67+
return Objects.hash(field, groupIndex);
68+
}
69+
70+
@Override
71+
public String toString() {
72+
return "PatchField{" + "field='" + field + '\'' + ", groupIndex=" + groupIndex + '}';
73+
}
74+
}

sormas-api/src/main/java/de/symeda/sormas/api/patch/CaseDataPatchRequest.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import javax.validation.constraints.NotNull;
99

1010
import de.symeda.sormas.api.Language;
11+
import de.symeda.sormas.api.externalmessage.survey.PatchDictionary;
1112
import de.symeda.sormas.api.info.InfoFacade;
1213

1314
/**
@@ -31,7 +32,7 @@ public class CaseDataPatchRequest {
3132
* The accepted fields are those from {@link InfoFacade#generateDataDictionary()}.
3233
*/
3334
@NotNull
34-
private Map<String, Object> patchDictionary;
35+
private PatchDictionary patchDictionary;
3536

3637
/**
3738
* Origin that wants the patch operation.
@@ -70,15 +71,22 @@ public CaseDataPatchRequest setReplacementStrategy(DataReplacementStrategy repla
7071
return this;
7172
}
7273

73-
public Map<String, Object> getPatchDictionary() {
74+
public PatchDictionary getPatchDictionary() {
7475
return patchDictionary;
7576
}
7677

77-
public CaseDataPatchRequest setPatchDictionary(Map<String, Object> patchDictionary) {
78+
public CaseDataPatchRequest setPatchDictionary(PatchDictionary patchDictionary) {
7879
this.patchDictionary = patchDictionary;
7980
return this;
8081
}
8182

83+
public CaseDataPatchRequest setPatchDictionary(Map<String, Object> patchDictionary) {
84+
PatchDictionary patchDictionaryWrapper = new PatchDictionary();
85+
patchDictionary.forEach(patchDictionaryWrapper::put);
86+
this.patchDictionary = patchDictionaryWrapper;
87+
return this;
88+
}
89+
8290
public EmptyValueBehavior getEmptyValueBehavior() {
8391
return emptyValueBehavior;
8492
}

sormas-api/src/main/java/de/symeda/sormas/api/patch/DataPatchResponse.java

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
import org.apache.commons.collections4.MapUtils;
88

9+
import de.symeda.sormas.api.externalmessage.survey.PatchDictionary;
10+
import de.symeda.sormas.api.externalmessage.survey.PatchField;
11+
912
/**
1013
* Response to a patch request.
1114
*/
@@ -25,37 +28,37 @@ public class DataPatchResponse implements Serializable {
2528
* Actual patched values for the specified keys.
2629
* Will NOT contain fields that were NOT patched (even though passed in original patchDictionary).
2730
*/
28-
private LinkedHashMap<String, Object> validPatchDictionary = new LinkedHashMap<>();
31+
private PatchDictionary validPatchDictionary = new PatchDictionary();
2932

3033
/**
3134
* Provides the reason for the failure for the impacted fields.
3235
*/
33-
private LinkedHashMap<String, DataPatchFailure> failures = new LinkedHashMap<>();
36+
private LinkedHashMap<PatchField, DataPatchFailure> failures = new LinkedHashMap<>();
3437

35-
public LinkedHashMap<String, Object> getValidPatchDictionary() {
36-
return validPatchDictionary;
38+
public boolean isApplied() {
39+
return applied;
3740
}
3841

39-
public DataPatchResponse setValidPatchDictionary(LinkedHashMap<String, Object> validPatchDictionary) {
40-
this.validPatchDictionary = validPatchDictionary;
42+
public DataPatchResponse setApplied(boolean applied) {
43+
this.applied = applied;
4144
return this;
4245
}
4346

44-
public LinkedHashMap<String, DataPatchFailure> getFailures() {
45-
return failures;
47+
public PatchDictionary getValidPatchDictionary() {
48+
return validPatchDictionary;
4649
}
4750

48-
public DataPatchResponse setFailures(LinkedHashMap<String, DataPatchFailure> failures) {
49-
this.failures = failures;
51+
public DataPatchResponse setValidPatchDictionary(PatchDictionary validPatchDictionary) {
52+
this.validPatchDictionary = validPatchDictionary;
5053
return this;
5154
}
5255

53-
public boolean isApplied() {
54-
return applied;
56+
public LinkedHashMap<PatchField, DataPatchFailure> getFailures() {
57+
return failures;
5558
}
5659

57-
public DataPatchResponse setApplied(boolean applied) {
58-
this.applied = applied;
60+
public DataPatchResponse setFailures(LinkedHashMap<PatchField, DataPatchFailure> failures) {
61+
this.failures = failures;
5962
return this;
6063
}
6164

sormas-api/src/main/java/de/symeda/sormas/api/patch/SinglePatchResult.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,25 @@
33
import javax.annotation.Nullable;
44
import javax.validation.constraints.NotNull;
55

6+
import de.symeda.sormas.api.externalmessage.survey.PatchField;
7+
68
public class SinglePatchResult {
79

810
@NotNull
9-
private String fieldName;
11+
private PatchField field;
1012

1113
@Nullable
1214
private Object value;
1315

1416
@Nullable
1517
private DataPatchFailure failure;
1618

17-
public String getFieldName() {
18-
return fieldName;
19+
public PatchField getField() {
20+
return field;
1921
}
2022

21-
public SinglePatchResult setFieldName(String fieldName) {
22-
this.fieldName = fieldName;
23+
public SinglePatchResult setField(PatchField field) {
24+
this.field = field;
2325
return this;
2426
}
2527

sormas-api/src/main/java/de/symeda/sormas/api/utils/Tuple.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ public static <F, S> Tuple<F, S> of(final F first, final S second) {
1111
return new Tuple<>(first, second);
1212
}
1313

14+
public static <F, S> Tuple<F, S> firstOnly(final F first) {
15+
return new Tuple<>(first, null);
16+
}
17+
18+
public static <F, S> Tuple<F, S> secondOnly(final S second) {
19+
return new Tuple<>(null, second);
20+
}
21+
1422
public Tuple(final F first, final S second) {
1523
this.first = first;
1624
this.second = second;

0 commit comments

Comments
 (0)