Skip to content

Commit ff0d0d1

Browse files
committed
MORE-Platform#204: PR and bug fixing
1 parent a147081 commit ff0d0d1

14 files changed

Lines changed: 191 additions & 129 deletions

File tree

studymanager-core/src/main/java/io/redlink/more/studymanager/core/sdk/MoreObservationSDK.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
import io.redlink.more.studymanager.core.io.TimeRange;
1212
import io.redlink.more.studymanager.core.properties.ObservationProperties;
1313
import io.redlink.more.studymanager.core.ui.DataViewData;
14-
import io.redlink.more.studymanager.core.ui.DataViewRow;
1514
import io.redlink.more.studymanager.core.ui.ViewConfig;
1615

1716
import java.util.Map;
1817
import java.util.Optional;
1918

2019
public interface MoreObservationSDK extends MorePlatformSDK {
2120

22-
void setPropertiesForParticipant(Integer participantId, ObservationProperties properties);
21+
void mergePropertiesForParticipant(Integer participantId, ObservationProperties properties);
22+
2323
Optional<ObservationProperties> getPropertiesForParticipant(Integer participantId);
2424

2525
void removePropertiesForParticipant(Integer participantId);

studymanager-observation/src/main/java/io/redlink/more/studymanager/component/observation/lime/LimeSurveyObservation.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public LimeSurveyObservation(MoreObservationSDK sdk, C properties, LimeSurveyReq
3434
}
3535

3636
@Override
37-
public void activate(){
37+
public void activate() {
3838
String surveyId = checkAndGetSurveyId();
3939

4040
//FIXME: This creates a LIME survey user for every participant, regardless if the Observation is relevant to the participant
@@ -43,13 +43,13 @@ public void activate(){
4343
participantIds.removeIf(id -> sdk.getPropertiesForParticipant(id).isPresent());
4444
limeSurveyRequestService.activateParticipants(participantIds, surveyId)
4545
.forEach(data ->
46-
sdk.setPropertiesForParticipant(
47-
Integer.parseInt(data.firstname()), //NOTE: both the firstname and lastname are set to the participantId
48-
new ObservationProperties(
49-
Map.of("token", data.token(),
50-
"limeUrl", limeSurveyRequestService.getBaseUrl())
51-
)
52-
)
46+
sdk.mergePropertiesForParticipant(
47+
Integer.parseInt(data.firstname()), //NOTE: both the firstname and lastname are set to the participantId
48+
new ObservationProperties(
49+
Map.of("token", data.token(),
50+
"limeUrl", limeSurveyRequestService.getBaseUrl())
51+
)
52+
)
5353
);
5454
limeSurveyRequestService.setSurveyEndUrl(surveyId, sdk.getStudyId(), sdk.getObservationId());
5555
limeSurveyRequestService.activateSurvey(surveyId);
@@ -78,7 +78,7 @@ public void deactivate() {
7878
String newSurveyId = properties.getString(LIME_SURVEY_ID);
7979
String activeSurveyId = sdk.getValue(LIME_SURVEY_ID, String.class).orElse(null);
8080

81-
if(activeSurveyId == null || activeSurveyId.equals(newSurveyId)) {
81+
if (activeSurveyId == null || activeSurveyId.equals(newSurveyId)) {
8282
sdk.setValue(LIME_SURVEY_ID, newSurveyId);
8383
}
8484
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package io.redlink.more.studymanager.model;
2+
3+
public record ParticipantObservationSeed(Long studyId, Integer participant, Integer observationId, Long seed) {
4+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package io.redlink.more.studymanager.model;
2+
3+
import java.util.Map;
4+
5+
public record ParticipantWithObservationProperties(
6+
Integer participantId,
7+
Long studyId,
8+
Integer observationId,
9+
Map<String, Object> properties
10+
) {
11+
}

studymanager-services/src/main/java/io/redlink/more/studymanager/repository/ObservationRepository.java

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,9 @@
1212
import io.redlink.more.studymanager.core.properties.ObservationProperties;
1313
import io.redlink.more.studymanager.exception.BadRequestException;
1414
import io.redlink.more.studymanager.model.Observation;
15+
import io.redlink.more.studymanager.model.ParticipantWithObservationProperties;
1516
import io.redlink.more.studymanager.model.scheduler.ScheduleEvent;
1617
import io.redlink.more.studymanager.utils.MapperUtils;
17-
18-
import java.util.Collection;
19-
import java.util.List;
20-
import java.util.Optional;
21-
2218
import org.slf4j.Logger;
2319
import org.slf4j.LoggerFactory;
2420
import org.springframework.dao.DataIntegrityViolationException;
@@ -29,6 +25,12 @@
2925
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
3026
import org.springframework.stereotype.Component;
3127

28+
import java.util.Collection;
29+
import java.util.Collections;
30+
import java.util.List;
31+
import java.util.Map;
32+
import java.util.Optional;
33+
3234
import static io.redlink.more.studymanager.repository.RepositoryUtils.getValidNullableIntegerValue;
3335

3436
@Component
@@ -46,6 +48,7 @@ public class ObservationRepository {
4648
private static final String DELETE_ALL = "DELETE FROM observations";
4749
private static final String SET_OBSERVATION_PROPERTIES_FOR_PARTICIPANT = "INSERT INTO participant_observation_properties(study_id,participant_id,observation_id,properties) VALUES (:study_id,:participant_id,:observation_id,:properties::jsonb) ON CONFLICT (study_id, participant_id, observation_id) DO UPDATE SET properties = EXCLUDED.properties";
4850
private static final String GET_OBSERVATION_PROPERTIES_FOR_PARTICIPANT = "SELECT properties FROM participant_observation_properties WHERE study_id = ? AND participant_id = ? AND observation_id = ?";
51+
private static final String GET_ALL_OBSERVATION_PROPERTIES_FOR_PARTICIPANT = "SELECT * FROM participant_observation_properties WHERE study_id = ?";
4952
private static final String DELETE_OBSERVATION_PROPERTIES_FOR_PARTICIPANT = "DELETE FROM participant_observation_properties WHERE study_id = ? AND participant_id = ? AND observation_id = ?";
5053

5154
private final JdbcTemplate template;
@@ -61,10 +64,10 @@ public Observation insert(Observation observation) {
6164
return namedTemplate.queryForObject(INSERT_NEW_OBSERVATION, toParams(observation), getObservationRowMapper());
6265
} catch (DataIntegrityViolationException e) {
6366
String message;
64-
if(observation.getStudyGroupId() != null && observation.getObservationGroupId() != null) {
67+
if (observation.getStudyGroupId() != null && observation.getObservationGroupId() != null) {
6568
message = String.format("Study group %s and/or observation group %s do not exist on study %s",
6669
observation.getStudyGroupId(), observation.getObservationGroupId(), observation.getStudyId());
67-
} else if(observation.getStudyGroupId() != null) {
70+
} else if (observation.getStudyGroupId() != null) {
6871
message = String.format("Study group %s does not exist on study %s",
6972
observation.getStudyGroupId(), observation.getStudyId());
7073
} else if (observation.getObservationGroupId() != null) {
@@ -75,9 +78,9 @@ public Observation insert(Observation observation) {
7578
LOG.warn("Unable to insert {}", observation, e);
7679
}
7780
throw new BadRequestException(message);
78-
} catch (JsonProcessingException e){
81+
} catch (JsonProcessingException e) {
7982
LOG.warn("Unable to insert {}", observation, e);
80-
throw new BadRequestException("Unable to insert observation (" + e.getClass().getSimpleName() + ": " + e.getMessage() +")");
83+
throw new BadRequestException("Unable to insert observation (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")");
8184
}
8285
}
8386

@@ -122,18 +125,20 @@ public List<Observation> listObservations(Long studyId) {
122125

123126
/**
124127
* Lists all Observation based for the parsed study, study group and as per default no assigned observation group
125-
* @param studyId the study
128+
*
129+
* @param studyId the study
126130
* @param studyGroupId the study group or NULL of none
127131
* @return the Observations
128132
*/
129133
public List<Observation> listObservationsForGroup(Long studyId, Integer studyGroupId) {
130-
return listObservationsForGroup(studyId, studyGroupId, List.of());
134+
return listObservationsForGroup(studyId, studyGroupId, List.of());
131135
}
132136

133137
/**
134138
* Lists all Observation based for the parsed study, study group and observation groups
135-
* @param studyId the study
136-
* @param studyGroupId the study group or NULL of none
139+
*
140+
* @param studyId the study
141+
* @param studyGroupId the study group or NULL of none
137142
* @param observationGroupIds the observation groups or an empty collection if none
138143
* @return the Observations
139144
*/
@@ -184,6 +189,40 @@ public Optional<ObservationProperties> getParticipantProperties(Long studyId, In
184189
}
185190
}
186191

192+
public void mergeParticipantProperties(Long studyId, Integer participantId, Integer observationId, ObservationProperties properties) {
193+
var oldProps = getParticipantProperties(studyId, participantId, observationId).orElse(new ObservationProperties());
194+
MapSqlParameterSource data = new MapSqlParameterSource()
195+
.addValue("study_id", studyId)
196+
.addValue("participant_id", participantId)
197+
.addValue("observation_id", observationId)
198+
.addValue("properties", MapperUtils.writeValueAsString(
199+
MapperUtils.mergeObjects(oldProps, properties))
200+
);
201+
202+
namedTemplate.update(SET_OBSERVATION_PROPERTIES_FOR_PARTICIPANT, data);
203+
}
204+
205+
206+
public List<ParticipantWithObservationProperties> getParticipantObservationProperties(Long studyId) {
207+
try {
208+
return template.query(
209+
GET_ALL_OBSERVATION_PROPERTIES_FOR_PARTICIPANT,
210+
getParticipantWithObservationPropertiesRowMapper(),
211+
studyId);
212+
} catch (EmptyResultDataAccessException e) {
213+
return Collections.emptyList();
214+
}
215+
}
216+
217+
private static RowMapper<ParticipantWithObservationProperties> getParticipantWithObservationPropertiesRowMapper() {
218+
return (rs, rowNum) -> new ParticipantWithObservationProperties(
219+
rs.getInt("participant_id"),
220+
rs.getLong("study_id"),
221+
rs.getInt("observation_id"),
222+
(Map<String, Object>) MapperUtils.readValue(rs.getString("properties"), Map.class)
223+
);
224+
}
225+
187226
public void removeParticipantProperties(Long studyId, Integer participantId, Integer observationId) {
188227
template.update(DELETE_OBSERVATION_PROPERTIES_FOR_PARTICIPANT, studyId, participantId, observationId);
189228
}
@@ -222,6 +261,6 @@ private static RowMapper<Observation> getObservationRowMapper() {
222261
.setModified(RepositoryUtils.readInstant(rs, "modified"))
223262
.setHidden(rs.getBoolean("hidden"))
224263
.setNoSchedule(rs.getBoolean("no_schedule"))
225-
.setObservationGroupId(RepositoryUtils.getValidNullableIntegerValue(rs,"observation_group_id"));
264+
.setObservationGroupId(RepositoryUtils.getValidNullableIntegerValue(rs, "observation_group_id"));
226265
}
227266
}

studymanager-services/src/main/java/io/redlink/more/studymanager/repository/ParticipantRepository.java

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
import com.google.common.base.Supplier;
1212
import io.redlink.more.studymanager.exception.BadRequestException;
1313
import io.redlink.more.studymanager.model.Participant;
14-
import io.redlink.more.studymanager.utils.MapperUtils;
15-
import jakarta.annotation.PostConstruct;
1614
import org.springframework.dao.DataIntegrityViolationException;
1715
import org.springframework.dao.EmptyResultDataAccessException;
1816
import org.springframework.jdbc.core.JdbcTemplate;
@@ -25,7 +23,6 @@
2523
import org.springframework.transaction.annotation.Transactional;
2624

2725
import java.util.List;
28-
import java.util.Map;
2926
import java.util.Optional;
3027
import java.util.Set;
3128

@@ -103,24 +100,15 @@ ON CONFLICT (study_id, participant_id) DO UPDATE SET token = excluded.token
103100
"INSERT INTO participant_observation_groups (study_id, participant_id, observation_group_id) " +
104101
"SELECT :study_id, :participant_id, unnest(:observation_group_ids::int[]);";
105102

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-
108103
private static final String DELETE_ALL = "DELETE FROM participants";
109104
private final JdbcTemplate template;
110105
private final NamedParameterJdbcTemplate namedTemplate;
111106

112-
private static ParticipantRepository instance;
113-
114107
public ParticipantRepository(JdbcTemplate template) {
115108
this.template = template;
116109
this.namedTemplate = new NamedParameterJdbcTemplate(template);
117110
}
118111

119-
@PostConstruct
120-
public void setInstance() {
121-
instance = this;
122-
}
123-
124112
@Transactional
125113
public Participant insert(Participant participant) {
126114
final KeyHolder keyHolder = new GeneratedKeyHolder();
@@ -177,23 +165,6 @@ public Optional<Participant> setStatusByIds(Long studyId, Integer participantId,
177165
).stream().findFirst();
178166
}
179167

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-
197168
@Transactional
198169
public void cleanupParticipant(Long studyId, Integer participantId) {
199170
final var params = toParams(studyId, participantId);
@@ -273,8 +244,4 @@ private void setParticipantObservationGroupIds(Long studyId, Integer participant
273244
namedTemplate.update(SET_PARTICIPANT_OBSERVATION_GROUP_IDS, params);
274245
}
275246
}
276-
277-
public static ParticipantRepository getInstance() {
278-
return instance;
279-
}
280247
}

studymanager-services/src/main/java/io/redlink/more/studymanager/sdk/MoreSDK.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
import io.redlink.more.studymanager.service.ElasticService;
3333
import io.redlink.more.studymanager.service.ParticipantService;
3434
import io.redlink.more.studymanager.service.PushNotificationService;
35+
import org.slf4j.Logger;
36+
import org.slf4j.LoggerFactory;
37+
import org.springframework.stereotype.Component;
38+
3539
import java.io.IOException;
3640
import java.time.Instant;
3741
import java.util.HashMap;
@@ -41,9 +45,6 @@
4145
import java.util.Set;
4246
import java.util.UUID;
4347
import java.util.stream.Collectors;
44-
import org.slf4j.Logger;
45-
import org.slf4j.LoggerFactory;
46-
import org.springframework.stereotype.Component;
4748

4849
@Component
4950
public class MoreSDK {
@@ -138,7 +139,7 @@ public void storeDatapoint(
138139
int extendedComponentId,
139140
String componentType,
140141
Instant time,
141-
Map<String,Object> data
142+
Map<String, Object> data
142143
) {
143144
switch (type) {
144145
case action -> elasticService.setDataPoint(studyId, new ElasticActionDataPoint(
@@ -168,8 +169,8 @@ public void storeDatapoint(
168169
}
169170
}
170171

171-
public void setPropertiesForParticipant(long studyId, Integer participantId, int observationId, ObservationProperties properties) {
172-
observationRepository.setParticipantProperties(studyId, participantId, observationId, properties);
172+
public void mergeParticipantProperties(long studyId, Integer participantId, int observationId, ObservationProperties properties) {
173+
observationRepository.mergeParticipantProperties(studyId, participantId, observationId, properties);
173174
}
174175

175176
public Optional<ObservationProperties> getPropertiesForParticipant(long studyId, Integer participantId, int observationId) {

studymanager-services/src/main/java/io/redlink/more/studymanager/sdk/scoped/MoreObservationSDKImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ public int getObservationId() {
5151
}
5252

5353
@Override
54-
public void setPropertiesForParticipant(Integer participantId, ObservationProperties properties) {
55-
sdk.setPropertiesForParticipant(
54+
public void mergePropertiesForParticipant(Integer participantId, ObservationProperties properties) {
55+
sdk.mergeParticipantProperties(
5656
this.studyId,
5757
participantId,
5858
this.observationId,

0 commit comments

Comments
 (0)