1111import com .google .common .base .Supplier ;
1212import io .redlink .more .studymanager .exception .BadRequestException ;
1313import io .redlink .more .studymanager .model .Participant ;
14- import java .util .List ;
15- import java .util .Optional ;
16- import java .util .Set ;
17-
14+ import io .redlink .more .studymanager .utils .MapperUtils ;
15+ import jakarta .annotation .PostConstruct ;
1816import org .springframework .dao .DataIntegrityViolationException ;
1917import org .springframework .dao .EmptyResultDataAccessException ;
2018import org .springframework .jdbc .core .JdbcTemplate ;
2624import org .springframework .stereotype .Component ;
2725import org .springframework .transaction .annotation .Transactional ;
2826
27+ import java .util .List ;
28+ import java .util .Map ;
29+ import java .util .Optional ;
30+ import java .util .Set ;
31+
2932import static io .redlink .more .studymanager .repository .RepositoryUtils .getValidNullableIntegerValue ;
3033import static io .redlink .more .studymanager .repository .RepositoryUtils .intReader ;
3134
@@ -41,53 +44,53 @@ ON CONFLICT (study_id, participant_id) DO UPDATE SET token = excluded.token
4144 """ ;
4245 private static final String GET_PARTICIPANT_BY_IDS =
4346 "SELECT " +
44- " p.participant_id, p.study_id, p.alias, p.study_group_id, r.token as token, p.status, p.created, " +
45- " p.modified, p.start, ARRAY_AGG(pog.observation_group_id) FILTER (WHERE pog.observation_group_id IS NOT NULL) AS observation_group_ids " +
46- "FROM participants p " +
47- " LEFT JOIN registration_tokens r ON p.study_id = r.study_id AND p.participant_id = r.participant_id " +
48- " LEFT JOIN participant_observation_groups pog ON p.study_id = pog.study_id AND p.participant_id = pog.participant_id " +
49- "WHERE p.study_id = ? AND p.participant_id = ? " +
50- "GROUP BY p.study_id, p.participant_id, r.token" ;
47+ " p.participant_id, p.study_id, p.alias, p.study_group_id, r.token as token, p.status, p.created, " +
48+ " p.modified, p.start, ARRAY_AGG(pog.observation_group_id) FILTER (WHERE pog.observation_group_id IS NOT NULL) AS observation_group_ids " +
49+ "FROM participants p " +
50+ " LEFT JOIN registration_tokens r ON p.study_id = r.study_id AND p.participant_id = r.participant_id " +
51+ " LEFT JOIN participant_observation_groups pog ON p.study_id = pog.study_id AND p.participant_id = pog.participant_id " +
52+ "WHERE p.study_id = ? AND p.participant_id = ? " +
53+ "GROUP BY p.study_id, p.participant_id, r.token" ;
5154 private static final String LIST_PARTICIPANTS_BY_STUDY =
5255 "SELECT " +
53- " p.participant_id, p.study_id, p.alias, p.study_group_id, r.token as token, p.status, p.created, " +
54- " p.modified, p.start, ARRAY_AGG(pog.observation_group_id) FILTER (WHERE pog.observation_group_id IS NOT NULL) AS observation_group_ids " +
55- "FROM participants p " +
56- " LEFT JOIN registration_tokens r ON p.study_id = r.study_id AND p.participant_id = r.participant_id " +
57- " LEFT JOIN participant_observation_groups pog ON p.study_id = pog.study_id AND p.participant_id = pog.participant_id " +
58- "WHERE p.study_id = ? " +
59- "GROUP BY p.study_id, p.participant_id, r.token" ;
56+ " p.participant_id, p.study_id, p.alias, p.study_group_id, r.token as token, p.status, p.created, " +
57+ " p.modified, p.start, ARRAY_AGG(pog.observation_group_id) FILTER (WHERE pog.observation_group_id IS NOT NULL) AS observation_group_ids " +
58+ "FROM participants p " +
59+ " LEFT JOIN registration_tokens r ON p.study_id = r.study_id AND p.participant_id = r.participant_id " +
60+ " LEFT JOIN participant_observation_groups pog ON p.study_id = pog.study_id AND p.participant_id = pog.participant_id " +
61+ "WHERE p.study_id = ? " +
62+ "GROUP BY p.study_id, p.participant_id, r.token" ;
6063 private static final String DELETE_PARTICIPANT =
6164 "DELETE FROM participants " +
62- "WHERE study_id=? AND participant_id=?" ;
65+ "WHERE study_id=? AND participant_id=?" ;
6366 private static final String UPDATE_PARTICIPANT =
6467 "UPDATE participants " +
65- "SET alias = :alias, study_group_id = :study_group_id, modified = now() " +
66- "WHERE study_id = :study_id AND participant_id = :participant_id" ;
68+ "SET alias = :alias, study_group_id = :study_group_id, modified = now() " +
69+ "WHERE study_id = :study_id AND participant_id = :participant_id" ;
6770 private static final String SET_STATUS =
6871 "UPDATE participants p SET status = :status::participant_status, modified = now() " +
69- "WHERE study_id = :study_id AND participant_id = :participant_id " +
70- "RETURNING *, " +
71- " (SELECT token FROM registration_tokens t WHERE t.study_id = p.study_id AND t.participant_id = p.participant_id ) as token, " +
72- " (SELECT ARRAY_AGG(observation_group_id) FROM participant_observation_groups pog WHERE pog.study_id = p.study_id AND pog.participant_id = p.participant_id ) as observation_group_ids" ;
72+ "WHERE study_id = :study_id AND participant_id = :participant_id " +
73+ "RETURNING *, " +
74+ " (SELECT token FROM registration_tokens t WHERE t.study_id = p.study_id AND t.participant_id = p.participant_id ) as token, " +
75+ " (SELECT ARRAY_AGG(observation_group_id) FROM participant_observation_groups pog WHERE pog.study_id = p.study_id AND pog.participant_id = p.participant_id ) as observation_group_ids" ;
7376 private static final String SET_STATUS_IF =
7477 "UPDATE participants p SET status= :new_status::participant_status, modified = now() " +
75- "WHERE study_id = :study_id AND participant_id = :participant_id " +
76- " AND status = :current_status::participant_status " +
77- "RETURNING *, (SELECT token FROM registration_tokens t WHERE t.study_id = p.study_id AND t.participant_id = p.participant_id ) as token" ;
78+ "WHERE study_id = :study_id AND participant_id = :participant_id " +
79+ " AND status = :current_status::participant_status " +
80+ "RETURNING *, (SELECT token FROM registration_tokens t WHERE t.study_id = p.study_id AND t.participant_id = p.participant_id ) as token" ;
7881
7982 private static final String LIST_PARTICIPANTS_FOR_CLOSING =
8083 "SELECT DISTINCT p.*, 't' as token, ARRAY_AGG(pog.observation_group_id) AS observation_group_ids " +
81- "FROM studies s " +
82- " JOIN participants p ON s.study_id = p.study_id " +
83- " LEFT JOIN study_groups sg ON p.study_group_id = sg.study_group_id AND p.study_id = sg.study_id " +
84- " LEFT JOIN participant_observation_groups pog ON p.study_id = pog.study_id AND p.participant_id = pog.participant_id " +
85- "WHERE s.status = 'active' " +
86- " AND p.status = 'active' " +
87- " AND p.start IS NOT NULL " +
88- " AND COALESCE(sg.duration, s.duration) IS NOT NULL " +
89- " AND (p.start + ((COALESCE(sg.duration, s.duration)->>'value')::int || ' ' || (COALESCE(sg.duration, s.duration)->>'unit'))::interval) < NOW()" +
90- "GROUP BY p.study_id, p.participant_id" ;
84+ "FROM studies s " +
85+ " JOIN participants p ON s.study_id = p.study_id " +
86+ " LEFT JOIN study_groups sg ON p.study_group_id = sg.study_group_id AND p.study_id = sg.study_id " +
87+ " LEFT JOIN participant_observation_groups pog ON p.study_id = pog.study_id AND p.participant_id = pog.participant_id " +
88+ "WHERE s.status = 'active' " +
89+ " AND p.status = 'active' " +
90+ " AND p.start IS NOT NULL " +
91+ " AND COALESCE(sg.duration, s.duration) IS NOT NULL " +
92+ " AND (p.start + ((COALESCE(sg.duration, s.duration)->>'value')::int || ' ' || (COALESCE(sg.duration, s.duration)->>'unit'))::interval) < NOW()" +
93+ "GROUP BY p.study_id, p.participant_id" ;
9194
9295 /*
9396 * SQL Statements for managing participant_observation_groups mapping for participants
@@ -100,15 +103,24 @@ ON CONFLICT (study_id, participant_id) DO UPDATE SET token = excluded.token
100103 "INSERT INTO participant_observation_groups (study_id, participant_id, observation_group_id) " +
101104 "SELECT :study_id, :participant_id, unnest(:observation_group_ids::int[]);" ;
102105
106+ private static final String GET_PARTICIPANT_OBSERVATION_PROPERTIES = "SELECT properties FROM participant_observation_properties WHERE participant_id = :participant_id AND study_id = :study_id AND observation_id = :observation_id" ;
107+
103108 private static final String DELETE_ALL = "DELETE FROM participants" ;
104109 private final JdbcTemplate template ;
105110 private final NamedParameterJdbcTemplate namedTemplate ;
106111
112+ private static ParticipantRepository instance ;
113+
107114 public ParticipantRepository (JdbcTemplate template ) {
108115 this .template = template ;
109116 this .namedTemplate = new NamedParameterJdbcTemplate (template );
110117 }
111118
119+ @ PostConstruct
120+ public void setInstance () {
121+ instance = this ;
122+ }
123+
112124 @ Transactional
113125 public Participant insert (Participant participant ) {
114126 final KeyHolder keyHolder = new GeneratedKeyHolder ();
@@ -145,6 +157,7 @@ public void deleteParticipant(Long studyId, Integer participantId) {
145157
146158 /**
147159 * Updates the participant and the {@link Participant#getObservationGroupIds()}
160+ *
148161 * @param participant
149162 * @return the updated participant as stored in the database
150163 */
@@ -164,6 +177,23 @@ public Optional<Participant> setStatusByIds(Long studyId, Integer participantId,
164177 ).stream ().findFirst ();
165178 }
166179
180+ @ Transactional
181+ public Optional <Map <String , Object >> getParticipantWithObservationProperties (Long studyId , Integer participantId , Integer observationId ) {
182+ try {
183+ return namedTemplate .query (
184+ GET_PARTICIPANT_OBSERVATION_PROPERTIES ,
185+ new MapSqlParameterSource ()
186+ .addValue ("study_id" , studyId )
187+ .addValue ("participant_id" , participantId )
188+ .addValue ("observation_id" , observationId ),
189+ (rs , rowNum ) ->
190+ (Map <String , Object >) MapperUtils .readValue (rs .getObject ("properties" ), Map .class )
191+ ).stream ().findFirst ();
192+ } catch (EmptyResultDataAccessException e ) {
193+ return Optional .empty ();
194+ }
195+ }
196+
167197 @ Transactional
168198 public void cleanupParticipant (Long studyId , Integer participantId ) {
169199 final var params = toParams (studyId , participantId );
@@ -238,10 +268,13 @@ private static RowMapper<Participant> getParticipantRowMapper() {
238268 private void setParticipantObservationGroupIds (Long studyId , Integer participantId , Set <Integer > observationGroupIds ) {
239269 final var params = toParams (studyId , participantId );
240270 namedTemplate .update (DELETE_PARTICIPANT_OBSERVATION_GROUP_IDS , params );
241- if (observationGroupIds != null && !observationGroupIds .isEmpty ()) {
271+ if (observationGroupIds != null && !observationGroupIds .isEmpty ()) {
242272 params .addValue ("observation_group_ids" , observationGroupIds .toArray (new Integer [0 ]));
243273 namedTemplate .update (SET_PARTICIPANT_OBSERVATION_GROUP_IDS , params );
244274 }
245275 }
246276
277+ public static ParticipantRepository getInstance () {
278+ return instance ;
279+ }
247280}
0 commit comments