1616package de .symeda .sormas .backend .externalmessage .labmessage ;
1717
1818import java .text .Collator ;
19- import java .util .Comparator ;
20- import java .util .Date ;
21- import java .util .List ;
22- import java .util .Objects ;
23- import java .util .Set ;
19+ import java .util .*;
2420import java .util .concurrent .CompletableFuture ;
2521import java .util .concurrent .CompletionStage ;
2622import java .util .concurrent .ExecutionException ;
3733import org .slf4j .Logger ;
3834import org .slf4j .LoggerFactory ;
3935
36+ import de .symeda .sormas .api .CountryHelper ;
4037import de .symeda .sormas .api .Disease ;
4138import de .symeda .sormas .api .caze .CaseDataDto ;
4239import de .symeda .sormas .api .caze .CaseSelectionDto ;
6461import de .symeda .sormas .api .utils .dataprocessing .HandlerCallback ;
6562import de .symeda .sormas .api .utils .dataprocessing .PickOrCreateEntryResult ;
6663import de .symeda .sormas .api .utils .dataprocessing .ProcessingResult ;
64+ import de .symeda .sormas .api .utils .luxembourg .LuxembourgNationalHealthIdValidator ;
6765import de .symeda .sormas .backend .caze .CaseFacadeEjb .CaseFacadeEjbLocal ;
6866import de .symeda .sormas .backend .caze .CaseService ;
67+ import de .symeda .sormas .backend .common .ConfigFacadeEjb .ConfigFacadeEjbLocal ;
6968import de .symeda .sormas .backend .disease .DiseaseConfigurationFacadeEjb .DiseaseConfigurationFacadeEjbLocal ;
7069import de .symeda .sormas .backend .person .PersonFacadeEjb .PersonFacadeEjbLocal ;
7170import de .symeda .sormas .backend .sample .PathogenTestFacadeEjb .PathogenTestFacadeEjbLocal ;
@@ -82,6 +81,8 @@ public class AutomaticLabMessageProcessor {
8281 @ PersistenceContext (unitName = ModelConstants .PERSISTENCE_UNIT_NAME )
8382 private EntityManager em ;
8483
84+ @ EJB
85+ private ConfigFacadeEjbLocal configFacade ;
8586 @ EJB
8687 private UserFacadeEjbLocal userFacade ;
8788 @ EJB
@@ -138,8 +139,74 @@ protected CompletionStage<Boolean> handleRelatedForwardedMessages() {
138139 throw new UnsupportedOperationException ("Related forwarded messages not supported yet" );
139140 }
140141
141- @ Override
142- protected void handlePickOrCreatePerson (PersonDto person , HandlerCallback <EntitySelection <PersonDto >> callback ) {
142+ /**
143+ * Handles person picking/creation with localized logic.
144+ * In case of Luxembourg, this method checks for a valid national health ID
145+ * and attempts to find an exact matching person.
146+ * Other country specific handling could be added to this method in the future.
147+ *
148+ * @param person
149+ * The {@link PersonDto} to process.
150+ * @param callback
151+ * The {@link HandlerCallback} to deliver the result of the
152+ * operation.
153+ * @return {@code true} if the person was handled by this method (either found
154+ * or created),
155+ * {@code false} otherwise.
156+ */
157+ protected boolean localizedHandlePickOrCreatePerson (PersonDto person , HandlerCallback <EntitySelection <PersonDto >> callback ) {
158+
159+ if (configFacade .isConfiguredCountry (CountryHelper .COUNTRY_CODE_LUXEMBOURG )) {
160+ String nationalHealthId = person .getNationalHealthId ();
161+ if (StringUtils .isBlank (nationalHealthId )) {
162+ logger .debug ("[MESSAGE PROCESSING] Incoming person's national health ID is blank. Canceling processing." );
163+ callback .cancel ();
164+ return true ;
165+ }
166+
167+ if (!LuxembourgNationalHealthIdValidator .isValid (nationalHealthId , null , null , null )) {
168+ logger .debug ("[MESSAGE PROCESSING] Incoming person's national health ID is not valid. Canceling processing." );
169+ callback .cancel ();
170+ return true ;
171+ }
172+
173+ final List <PersonDto > matchingPersons = personFacade .getByNationalHealthId (nationalHealthId );
174+
175+ // Multiple persons matched
176+ if (matchingPersons .size () > 1 ) {
177+ logger
178+ .debug ("[MESSAGE PROCESSING] Multiple persons with the same national health id found in the database. Canceling processing." );
179+ callback .cancel ();
180+ return true ;
181+ }
182+
183+ // No persons matched
184+ if (matchingPersons .isEmpty ()) {
185+ callback .done (new EntitySelection <>(personFacade .save (person ), true ));
186+ return true ;
187+ }
188+
189+ // Exactly one person matched
190+ callback .done (new EntitySelection <>(matchingPersons .get (0 ), false ));
191+ return true ;
192+ }
193+
194+ return false ;
195+ }
196+
197+ /**
198+ * Handles person picking/creation with default logic. This method checks for a
199+ * national health ID. If present, it searches for matching persons. If no ID is
200+ * found, it checks for similar persons based on name.
201+ *
202+ * @param person
203+ * The {@link PersonDto} to process.
204+ * @param callback
205+ * The {@link HandlerCallback} to deliver the result of the
206+ * operation.
207+ */
208+ protected void defaultHandlePickOrCreatePerson (PersonDto person , HandlerCallback <EntitySelection <PersonDto >> callback ) {
209+
143210 String nationalHealthId = person .getNationalHealthId ();
144211 if (StringUtils .isNotBlank (nationalHealthId )) {
145212 List <PersonDto > matchingPersons = personFacade .getByNationalHealthId (nationalHealthId );
@@ -163,6 +230,29 @@ protected void handlePickOrCreatePerson(PersonDto person, HandlerCallback<Entity
163230 }
164231 }
165232
233+ /**
234+ * Handles the process of picking an existing person or creating a new one.
235+ * This method first attempts to use localized handling. If that fails, it
236+ * defaults to the general handling logic.
237+ *
238+ * @param person
239+ * The {@link PersonDto} to process.
240+ * @param callback
241+ * The {@link HandlerCallback} to deliver the result of the
242+ * operation.
243+ */
244+ @ Override
245+ protected void handlePickOrCreatePerson (PersonDto person , HandlerCallback <EntitySelection <PersonDto >> callback ) {
246+
247+ // try to see if any localized handling is processing it
248+ if (localizedHandlePickOrCreatePerson (person , callback )) {
249+ return ;
250+ }
251+
252+ // no localized handling was do so go with default
253+ defaultHandlePickOrCreatePerson (person , callback );
254+ }
255+
166256 @ Override
167257 protected void handlePickOrCreateEntry (
168258 List <CaseSelectionDto > similarCases ,
0 commit comments