Skip to content

Commit cb6cd1e

Browse files
authored
Merge pull request #15 from redlink-gmbh/umm/204-integrate-randomizer-algorithm
2 parents b300f8a + f20d1d0 commit cb6cd1e

19 files changed

Lines changed: 1083 additions & 162 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/model/scheduler/Event.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
package io.redlink.more.studymanager.model.scheduler;
1010

1111
import com.fasterxml.jackson.annotation.JsonFormat;
12+
1213
import java.time.Instant;
1314

1415
public class Event implements ScheduleEvent {
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
package io.redlink.more.studymanager.model.scheduler;
22

33
public record Randomization(boolean state, int duration) {
4-
54
}

studymanager-services/src/main/java/io/redlink/more/studymanager/model/scheduler/ScheduleEvent.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,9 @@
2222
@JsonSubTypes.Type(value = RelativeEvent.class, name = RelativeEvent.TYPE)
2323
})
2424
public interface ScheduleEvent {
25-
public String getType();
25+
String getType();
26+
27+
Randomization getRandomization();
28+
29+
ScheduleEvent setRandomization(Randomization randomization);
2630
}

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

Lines changed: 54 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;
@@ -28,6 +24,13 @@
2824
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
2925
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
3026
import org.springframework.stereotype.Component;
27+
import org.springframework.transaction.annotation.Transactional;
28+
29+
import java.util.Collection;
30+
import java.util.Collections;
31+
import java.util.List;
32+
import java.util.Map;
33+
import java.util.Optional;
3134

3235
import static io.redlink.more.studymanager.repository.RepositoryUtils.getValidNullableIntegerValue;
3336

@@ -46,6 +49,7 @@ public class ObservationRepository {
4649
private static final String DELETE_ALL = "DELETE FROM observations";
4750
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";
4851
private static final String GET_OBSERVATION_PROPERTIES_FOR_PARTICIPANT = "SELECT properties FROM participant_observation_properties WHERE study_id = ? AND participant_id = ? AND observation_id = ?";
52+
private static final String GET_ALL_OBSERVATION_PROPERTIES_FOR_PARTICIPANT = "SELECT * FROM participant_observation_properties WHERE study_id = ?";
4953
private static final String DELETE_OBSERVATION_PROPERTIES_FOR_PARTICIPANT = "DELETE FROM participant_observation_properties WHERE study_id = ? AND participant_id = ? AND observation_id = ?";
5054

5155
private final JdbcTemplate template;
@@ -61,10 +65,10 @@ public Observation insert(Observation observation) {
6165
return namedTemplate.queryForObject(INSERT_NEW_OBSERVATION, toParams(observation), getObservationRowMapper());
6266
} catch (DataIntegrityViolationException e) {
6367
String message;
64-
if(observation.getStudyGroupId() != null && observation.getObservationGroupId() != null) {
68+
if (observation.getStudyGroupId() != null && observation.getObservationGroupId() != null) {
6569
message = String.format("Study group %s and/or observation group %s do not exist on study %s",
6670
observation.getStudyGroupId(), observation.getObservationGroupId(), observation.getStudyId());
67-
} else if(observation.getStudyGroupId() != null) {
71+
} else if (observation.getStudyGroupId() != null) {
6872
message = String.format("Study group %s does not exist on study %s",
6973
observation.getStudyGroupId(), observation.getStudyId());
7074
} else if (observation.getObservationGroupId() != null) {
@@ -75,9 +79,9 @@ public Observation insert(Observation observation) {
7579
LOG.warn("Unable to insert {}", observation, e);
7680
}
7781
throw new BadRequestException(message);
78-
} catch (JsonProcessingException e){
82+
} catch (JsonProcessingException e) {
7983
LOG.warn("Unable to insert {}", observation, e);
80-
throw new BadRequestException("Unable to insert observation (" + e.getClass().getSimpleName() + ": " + e.getMessage() +")");
84+
throw new BadRequestException("Unable to insert observation (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")");
8185
}
8286
}
8387

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

123127
/**
124128
* Lists all Observation based for the parsed study, study group and as per default no assigned observation group
125-
* @param studyId the study
129+
*
130+
* @param studyId the study
126131
* @param studyGroupId the study group or NULL of none
127132
* @return the Observations
128133
*/
129134
public List<Observation> listObservationsForGroup(Long studyId, Integer studyGroupId) {
130-
return listObservationsForGroup(studyId, studyGroupId, List.of());
135+
return listObservationsForGroup(studyId, studyGroupId, List.of());
131136
}
132137

133138
/**
134139
* 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
140+
*
141+
* @param studyId the study
142+
* @param studyGroupId the study group or NULL of none
137143
* @param observationGroupIds the observation groups or an empty collection if none
138144
* @return the Observations
139145
*/
@@ -184,6 +190,40 @@ public Optional<ObservationProperties> getParticipantProperties(Long studyId, In
184190
}
185191
}
186192

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

0 commit comments

Comments
 (0)