use of org.sagebionetworks.bridge.models.healthdata.HealthDataSubmission in project BridgeServer2 by Sage-Bionetworks.
the class HealthDataServiceSubmitHealthDataTest method submitHealthDataBySchema.
@Test
public void submitHealthDataBySchema() throws Exception {
// mock schema service
List<UploadFieldDefinition> fieldDefList = ImmutableList.of(new UploadFieldDefinition.Builder().withName("sanitize____this").withType(UploadFieldType.STRING).build(), new UploadFieldDefinition.Builder().withName("no-value-field").withType(UploadFieldType.STRING).withRequired(false).build(), new UploadFieldDefinition.Builder().withName("null-value-field").withType(UploadFieldType.STRING).withRequired(false).build(), new UploadFieldDefinition.Builder().withName("attachment-field").withType(UploadFieldType.ATTACHMENT_V2).build(), new UploadFieldDefinition.Builder().withName("normal-field").withType(UploadFieldType.STRING).build());
schema.setFieldDefinitions(fieldDefList);
// setup input
ObjectNode inputData = BridgeObjectMapper.get().createObjectNode();
inputData.put("sanitize!@#$this", "sanitize this value");
inputData.putNull("null-value-field");
inputData.put("attachment-field", "attachment field value");
inputData.put("normal-field", "normal field value");
inputData.put("non-schema-field", "this is not in the schema");
ObjectNode inputMetadata = BridgeObjectMapper.get().createObjectNode();
inputMetadata.put("sample-metadata-key", "sample-metadata-value");
HealthDataSubmission submission = makeValidBuilderWithSchema().withData(inputData).withMetadata(inputMetadata).build();
// execute
HealthDataRecord svcOutputRecord = svc.submitHealthData(TEST_APP_ID, PARTICIPANT, submission);
// verify that we return the record returned by the internal getRecordById() call.
assertSame(svcOutputRecord, createdRecord);
// Verify strict validation handler called. While we're at it, verify that we constructed the context and
// record correctly.
ArgumentCaptor<UploadValidationContext> contextCaptor = ArgumentCaptor.forClass(UploadValidationContext.class);
verify(mockStrictValidationHandler).handle(contextCaptor.capture());
UploadValidationContext context = contextCaptor.getValue();
assertEquals(context.getHealthCode(), HEALTH_CODE);
assertEquals(context.getAppId(), TEST_APP_ID);
// We generate an upload ID and use it for the record ID.
String uploadId = context.getUploadId();
assertNotNull(uploadId);
assertEquals(context.getRecordId(), uploadId);
// We have one attachment. This is text because we passed in text. This will normally be arrays or objects.
ArgumentCaptor<JsonNode> attachmentNodeCaptor = ArgumentCaptor.forClass(JsonNode.class);
verify(mockUploadFileHelper).uploadJsonNodeAsAttachment(attachmentNodeCaptor.capture(), eq(uploadId), eq("attachment-field"));
JsonNode attachmentNode = attachmentNodeCaptor.getValue();
assertEquals(attachmentNode.textValue(), "attachment field value");
// validate the created record
HealthDataRecord contextRecord = context.getHealthDataRecord();
assertEquals(contextRecord.getAppVersion(), APP_VERSION);
assertEquals(contextRecord.getPhoneInfo(), PHONE_INFO);
assertEquals(contextRecord.getSchemaId(), SCHEMA_ID);
assertEquals(contextRecord.getSchemaRevision().intValue(), SCHEMA_REV);
assertEquals(contextRecord.getHealthCode(), HEALTH_CODE);
assertEquals(contextRecord.getAppId(), TEST_APP_ID);
assertEquals(contextRecord.getUploadDate(), MOCK_NOW_DATE);
assertEquals(contextRecord.getUploadedOn().longValue(), MOCK_NOW_MILLIS);
assertEquals(contextRecord.getCreatedOn().longValue(), CREATED_ON_MILLIS);
assertEquals(contextRecord.getCreatedOnTimeZone(), CREATED_ON_TIMEZONE);
// validate the sanitized data (includes attachments with attachment ID)
JsonNode sanitizedData = contextRecord.getData();
assertEquals(sanitizedData.size(), 3);
assertEquals(sanitizedData.get("sanitize____this").textValue(), "sanitize this value");
assertEquals(sanitizedData.get("attachment-field"), ATTACHMENT_ID_NODE);
assertEquals(sanitizedData.get("normal-field").textValue(), "normal field value");
// validate app version and phone info in metadata
JsonNode metadata = contextRecord.getMetadata();
assertEquals(metadata.size(), 2);
assertEquals(metadata.get(UploadUtil.FIELD_APP_VERSION).textValue(), APP_VERSION);
assertEquals(metadata.get(UploadUtil.FIELD_PHONE_INFO).textValue(), PHONE_INFO);
// validate client-submitted metadata (userMetadata)
JsonNode userMetadata = contextRecord.getUserMetadata();
assertEquals(userMetadata.size(), 1);
assertEquals(userMetadata.get("sample-metadata-key").textValue(), "sample-metadata-value");
// Validate raw data submitted to S3
String expectedRawDataAttachmentId = uploadId + HealthDataService.RAW_ATTACHMENT_SUFFIX;
ArgumentCaptor<byte[]> rawBytesCaptor = ArgumentCaptor.forClass(byte[].class);
verify(mockUploadFileHelper).uploadBytesAsAttachment(eq(expectedRawDataAttachmentId), rawBytesCaptor.capture());
assertEquals(contextRecord.getRawDataAttachmentId(), expectedRawDataAttachmentId);
byte[] rawBytes = rawBytesCaptor.getValue();
JsonNode rawJsonNode = BridgeObjectMapper.get().readTree(rawBytes);
assertEquals(rawJsonNode, inputData);
// validate the other handlers are called
verify(mockTranscribeConsentHandler).handle(context);
verify(mockUploadArtifactsHandler).handle(context);
// We get the record back using the upload ID.
verify(svc).getRecordById(uploadId);
}
use of org.sagebionetworks.bridge.models.healthdata.HealthDataSubmission in project BridgeServer2 by Sage-Bionetworks.
the class HealthDataServiceSubmitHealthDataTest method strictValidationThrows.
@Test(expectedExceptions = BadRequestException.class)
public void strictValidationThrows() throws Exception {
// mock schema service
List<UploadFieldDefinition> fieldDefList = ImmutableList.of(new UploadFieldDefinition.Builder().withName("simple-field").withType(UploadFieldType.INT).build());
schema.setFieldDefinitions(fieldDefList);
// mock handlers - Only StrictValidationHandler will be called. Also, since we're not calling the actual
// StrictValidationHandler, we need to make it throw.
doThrow(UploadValidationException.class).when(mockStrictValidationHandler).handle(any());
// setup input
ObjectNode inputData = BridgeObjectMapper.get().createObjectNode();
inputData.put("simple-field", "not an int");
HealthDataSubmission submission = makeValidBuilderWithSchema().withData(inputData).build();
// execute - This throws.
svc.submitHealthData(TEST_APP_ID, PARTICIPANT, submission);
}
use of org.sagebionetworks.bridge.models.healthdata.HealthDataSubmission in project BridgeServer2 by Sage-Bionetworks.
the class HealthDataServiceSubmitHealthDataTest method invalidSubmission.
@Test(expectedExceptions = InvalidEntityException.class)
public void invalidSubmission() throws Exception {
HealthDataSubmission submission = makeValidBuilderWithSchema().withData(null).build();
svc.submitHealthData(TEST_APP_ID, PARTICIPANT, submission);
}
use of org.sagebionetworks.bridge.models.healthdata.HealthDataSubmission in project BridgeServer2 by Sage-Bionetworks.
the class SmsServiceTest method verifyHealthData.
private void verifyHealthData(StudyParticipant expectedParticipant, DateTimeZone expectedTimeZone, SmsType expectedSmsType, String expectedMessage) throws Exception {
ArgumentCaptor<HealthDataSubmission> healthDataCaptor = ArgumentCaptor.forClass(HealthDataSubmission.class);
verify(mockHealthDataService).submitHealthData(eq(TEST_APP_ID), same(expectedParticipant), healthDataCaptor.capture());
HealthDataSubmission healthData = healthDataCaptor.getValue();
// Verify simple attributes.
assertEquals(healthData.getAppVersion(), SmsService.BRIDGE_SERVER_APP_VERSION);
assertEquals(healthData.getPhoneInfo(), SmsService.BRIDGE_SERVER_PHONE_INFO);
assertEquals(healthData.getSchemaId(), SmsService.MESSAGE_LOG_SCHEMA_ID);
assertEquals(healthData.getSchemaRevision().intValue(), SmsService.MESSAGE_LOG_SCHEMA_REV);
DateTime createdOn = healthData.getCreatedOn();
assertEquals(createdOn.getMillis(), MOCK_NOW_MILLIS);
assertEquals(createdOn.getZone().getOffset(createdOn), expectedTimeZone.getOffset(createdOn));
// Assert health data.
JsonNode healthDataNode = healthData.getData();
assertEquals(healthDataNode.get(SmsService.FIELD_NAME_SMS_TYPE).textValue(), expectedSmsType.getValue());
assertEquals(healthDataNode.get(SmsService.FIELD_NAME_MESSAGE_BODY).textValue(), expectedMessage);
// sentOn is createdOn in string form.
assertEquals(healthDataNode.get(SmsService.FIELD_NAME_SENT_ON).textValue(), createdOn.toString());
}
use of org.sagebionetworks.bridge.models.healthdata.HealthDataSubmission in project BridgeServer2 by Sage-Bionetworks.
the class HealthDataController method submitHealthData.
/**
* API to allow consented users to submit health data in a synchronous API, instead of using the asynchronous
* upload API. This is most beneficial for small data sets, like simple surveys. This API returns the health data
* record produced from this submission, which includes the record ID.
*/
@PostMapping(path = "/v3/healthdata", produces = { APPLICATION_JSON_UTF8_VALUE })
@ResponseStatus(HttpStatus.CREATED)
public String submitHealthData() throws IOException, UploadValidationException {
// Submit health data.
UserSession session = getAuthenticatedAndConsentedSession();
HealthDataSubmission healthDataSubmission = parseJson(HealthDataSubmission.class);
HealthDataRecord savedRecord = healthDataService.submitHealthData(session.getAppId(), session.getParticipant(), healthDataSubmission);
// Write record ID into the metrics, for logging and diagnostics.
Metrics metrics = getMetrics();
if (metrics != null) {
metrics.setRecordId(savedRecord.getId());
}
// Record upload time to user's request info. This allows us to track the last time the user submitted.
RequestInfo requestInfo = getRequestInfoBuilder(session).withUploadedOn(DateUtils.getCurrentDateTime()).build();
requestInfoService.updateRequestInfo(requestInfo);
// Return the record produced by this submission. Filter out Health Code, of course.
return HealthDataRecord.PUBLIC_RECORD_WRITER.writeValueAsString(savedRecord);
}
Aggregations