1717import org .slf4j .Logger ;
1818import org .slf4j .LoggerFactory ;
1919
20- import com .google .common .base .Suppliers ;
21-
2220import de .symeda .sormas .api .Disease ;
21+ import de .symeda .sormas .api .EntityDto ;
2322import de .symeda .sormas .api .caze .CaseDataDto ;
2423import de .symeda .sormas .api .patch .*;
2524import de .symeda .sormas .api .patch .mapping .FieldCustomMapper ;
2625import de .symeda .sormas .api .patch .mapping .FieldPatchRequest ;
2726import de .symeda .sormas .api .patch .mapping .ValueMappingResult ;
2827import de .symeda .sormas .api .patch .mapping .ValuePatchRequest ;
29- import de .symeda .sormas .api .person .PersonDto ;
3028import de .symeda .sormas .api .utils .Tuple ;
3129import de .symeda .sormas .api .utils .fieldvisibility .FieldVisibilityCheckers ;
3230import de .symeda .sormas .backend .common .ConfigFacadeEjb ;
4038@ ApplicationScoped
4139public class DataPatcherImpl implements DataPatcher {
4240
43- public static final String PERSON_FIELD_NAME_PREFIX = "Person." ;
44-
4541 private final static Logger logger = LoggerFactory .getLogger (DataPatcherImpl .class );
4642
4743 @ Inject
@@ -93,10 +89,8 @@ public DataPatchResponse patch(CaseDataPatchRequest request) {
9389
9490 Disease disease = caseData .getDisease ();
9591
96- // TODO: modify to make more "agnostic": person is any other entity.
97- // TODO: only case is different as it is the root.
98- // make this generic for additional "root"-types
99- Supplier <PersonDto > personSupplier = Suppliers .memoize (() -> getPersonDto (caseData ));
92+ Map <String , EntityDto > entityCache = new HashMap <>();
93+ entityCache .put (CaseDataDto .I18N_PREFIX , caseData );
10094
10195 List <Tuple <String , Tuple <DataPatchFailureCause , Object >>> patchingTuples = computePatchingTuples (request );
10296
@@ -105,7 +99,7 @@ public DataPatchResponse patch(CaseDataPatchRequest request) {
10599 de .symeda .sormas .api .patch .SinglePatchResult singlePatchResult =
106100 new de .symeda .sormas .api .patch .SinglePatchResult ().setFieldName (fullFieldName );
107101
108- Supplier <Object > target = () -> findAppropriateTarget (fullFieldName , caseData , personSupplier );
102+ Supplier <Object > target = () -> findAppropriateTarget (fullFieldName , caseData , entityCache );
109103
110104 try {
111105 return produceSinglePatchResult (request , entry , disease , target );
@@ -130,7 +124,7 @@ public DataPatchResponse patch(CaseDataPatchRequest request) {
130124 return response ;
131125 }
132126
133- saveDTOsIfAppropriate (validPatchDictionary , caseData , personSupplier );
127+ saveDTOsIfAppropriate (entityCache );
134128
135129 logger .debug ("dataPatchResponse: [{}]" , response );
136130
@@ -148,31 +142,21 @@ public SinglePatchResult produceSinglePatchResult(
148142 .orElseGet (() -> valueMappingResult (entry , disease , request , target ));
149143 }
150144
151- private void saveDTOsIfAppropriate (Map <String , Object > validPatchDictionary , CaseDataDto caseData , Supplier <PersonDto > personSupplier ) {
152- if (anyFieldPatchedWithPrefix (validPatchDictionary , PatchFieldHelper .CASE_DATA_PREFIX )) {
153- logger .info ("CaseData was modified will be applied for: [{}]. Enable debug to see fully patched object" , caseData );
154-
155- if (logger .isDebugEnabled ()) {
156- logger .debug ("CaseData: \n {}" , ObjectMapperProvider .writeValueAsStringFailSafe (caseData ));
157- }
145+ private void saveDTOsIfAppropriate (Map <String , EntityDto > entityCache ) {
146+ List <EntityDto > toSave = new ArrayList <>(entityCache .values ());
158147
159- businessDtoFacade .save (caseData );
148+ if (toSave .isEmpty ()) {
149+ return ;
160150 }
161151
162- if (anyFieldPatchedWithPrefix (validPatchDictionary , PatchFieldHelper .PERSON_PREFIX )) {
163- PersonDto person = personSupplier .get ();
164- logger .info ("Person was modified will be applied for: [{}]. Enable debug fully patched object" , person );
165-
152+ toSave .forEach (entity -> {
153+ logger .info ("{} was modified, will be saved. Enable debug to see fully patched object" , entity .getClass ().getSimpleName ());
166154 if (logger .isDebugEnabled ()) {
167- logger .debug ("Person : \n {}" , ObjectMapperProvider .writeValueAsStringFailSafe (person ));
155+ logger .debug ("{} : \n {}" , entity . getClass (). getSimpleName (), ObjectMapperProvider .writeValueAsStringFailSafe (entity ));
168156 }
157+ });
169158
170- businessDtoFacade .save (person );
171- }
172- }
173-
174- private boolean anyFieldPatchedWithPrefix (Map <String , Object > validPatchDictionary , String caseDataPrefix ) {
175- return validPatchDictionary .keySet ().stream ().anyMatch (key -> key .startsWith (caseDataPrefix ));
159+ businessDtoFacade .save (toSave );
176160 }
177161
178162 private @ NotNull <R > Map <String , R > buildDictionaryFor (
@@ -378,16 +362,6 @@ private Tuple<String, Tuple<DataPatchFailureCause, Object>> buildMapTupleEntryFr
378362 return request .getEmptyValueBehavior () == EmptyValueBehavior .REPLACE ? ignored -> true : buildEmptyValuePredicate ();
379363 }
380364
381- private @ NotNull PersonDto getPersonDto (CaseDataDto caseData ) {
382- String personUuid = caseData .getPerson ().getUuid ();
383- PersonDto person = businessDtoFacade .fetch (PersonDto .class , caseData );
384-
385- if (person == null ) {
386- throw new IllegalStateException (String .format ("No person found for uuid: [%s]" , personUuid ));
387- }
388- return person ;
389- }
390-
391365 private @ NotNull CaseDataDto getCaseDataDto (CaseDataPatchRequest request ) {
392366 String caseUuid = request .getCaseUuid ();
393367 CaseDataDto caseData = businessDtoFacade .getCaseDataDtoNullable (caseUuid );
@@ -398,14 +372,27 @@ private Tuple<String, Tuple<DataPatchFailureCause, Object>> buildMapTupleEntryFr
398372 return caseData ;
399373 }
400374
401- private Object findAppropriateTarget (String fieldName , CaseDataDto caseData , Supplier <PersonDto > person ) {
402- if (fieldName .startsWith (PERSON_FIELD_NAME_PREFIX )) {
403- return person .get ();
375+ private EntityDto findAppropriateTarget (String resolvedPath , CaseDataDto caseData , Map <String , EntityDto > entityCache ) {
376+ String prefix = extractPrefix (resolvedPath );
377+
378+ if (entityCache .containsKey (prefix )) {
379+ return entityCache .get (prefix );
380+ }
381+
382+ Optional <EntityDto > fetched = businessDtoFacade .tryFetchByI18nNameForCreateUpdate (prefix , caseData );
383+ if (fetched .isPresent ()) {
384+ entityCache .put (prefix , fetched .get ());
385+ return fetched .get ();
404386 }
405387
406388 return caseData ;
407389 }
408390
391+ private String extractPrefix (String fieldName ) {
392+ int dotIndex = fieldName .indexOf ('.' );
393+ return dotIndex == -1 ? fieldName : fieldName .substring (0 , dotIndex );
394+ }
395+
409396 private Predicate <Map .Entry <String , Object >> buildEmptyValuePredicate () {
410397
411398 return stringObjectEntry -> {
0 commit comments