Search in sources :

Example 1 with UploadFieldDefinition

use of org.sagebionetworks.bridge.models.upload.UploadFieldDefinition in project BridgeServer2 by Sage-Bionetworks.

the class DynamoAppTest method uploadMetadataFieldDefListIsNeverNull.

@Test
public void uploadMetadataFieldDefListIsNeverNull() {
    // make field for test
    List<UploadFieldDefinition> fieldDefList = new ArrayList<>();
    fieldDefList.add(new UploadFieldDefinition.Builder().withName("test-field").withType(UploadFieldType.ATTACHMENT_V2).build());
    // starts as empty
    App app = new DynamoApp();
    assertTrue(app.getUploadMetadataFieldDefinitions().isEmpty());
    // set value works
    app.setUploadMetadataFieldDefinitions(fieldDefList);
    assertEquals(app.getUploadMetadataFieldDefinitions(), fieldDefList);
    // set to null makes it empty again
    app.setUploadMetadataFieldDefinitions(null);
    assertTrue(app.getUploadMetadataFieldDefinitions().isEmpty());
}
Also used : UploadFieldDefinition(org.sagebionetworks.bridge.models.upload.UploadFieldDefinition) App(org.sagebionetworks.bridge.models.apps.App) ArrayList(java.util.ArrayList) Test(org.testng.annotations.Test) OAuthProviderTest(org.sagebionetworks.bridge.models.apps.OAuthProviderTest)

Example 2 with UploadFieldDefinition

use of org.sagebionetworks.bridge.models.upload.UploadFieldDefinition 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);
}
Also used : ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) UploadValidationContext(org.sagebionetworks.bridge.upload.UploadValidationContext) JsonNode(com.fasterxml.jackson.databind.JsonNode) UploadFieldDefinition(org.sagebionetworks.bridge.models.upload.UploadFieldDefinition) HealthDataSubmission(org.sagebionetworks.bridge.models.healthdata.HealthDataSubmission) HealthDataRecord(org.sagebionetworks.bridge.models.healthdata.HealthDataRecord) Test(org.testng.annotations.Test)

Example 3 with UploadFieldDefinition

use of org.sagebionetworks.bridge.models.upload.UploadFieldDefinition 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);
}
Also used : UploadFieldDefinition(org.sagebionetworks.bridge.models.upload.UploadFieldDefinition) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) HealthDataSubmission(org.sagebionetworks.bridge.models.healthdata.HealthDataSubmission) Test(org.testng.annotations.Test)

Example 4 with UploadFieldDefinition

use of org.sagebionetworks.bridge.models.upload.UploadFieldDefinition in project BridgeServer2 by Sage-Bionetworks.

the class UploadSchemaService method createUploadSchemaFromSurvey.

/**
 * <p>
 * Creates an upload schema from a survey. This is generally called when a survey is published, to
 * create the corresponding upload schema, so that health data records can be created from survey responses.
 * This method will also persist the schema to the backing store.
 * <p>
 * If newSchemaRev is true, this method will always create a new schema revision. If false, it will attempt to
 * modify the existing schema revision. However, if the schema revisions are not compatible, it will fall back to
 * creating a new schema revision.
 * </p>
 */
public UploadSchema createUploadSchemaFromSurvey(String appId, Survey survey, boolean newSchemaRev) {
    // https://sagebionetworks.jira.com/browse/BRIDGE-1698 - If the existing Schema ID points to a different survey
    // or a non-survey, this is an error. Having multiple surveys point to the same schema ID causes really bad
    // things to happen, and we need to prevent it.
    String schemaId = survey.getIdentifier();
    UploadSchema oldSchema = getUploadSchemaNoThrow(appId, schemaId);
    if (oldSchema != null) {
        if (oldSchema.getSchemaType() != UploadSchemaType.IOS_SURVEY || !Objects.equals(oldSchema.getSurveyGuid(), survey.getGuid())) {
            throw new BadRequestException("Survey with identifier " + schemaId + " conflicts with schema with the same ID. Please use a different survey identifier.");
        }
    }
    // the same survey.
    if (!newSchemaRev && oldSchema != null) {
        // Check that the old schema already has the answers field.
        List<UploadFieldDefinition> oldFieldDefList = oldSchema.getFieldDefinitions();
        UploadFieldDefinition answersFieldDef = getElement(oldFieldDefList, UploadFieldDefinition::getName, FIELD_ANSWERS).orElse(null);
        if (answersFieldDef == null) {
            // Old schema doesn't have the
            List<UploadFieldDefinition> newFieldDefList = new ArrayList<>(oldFieldDefList);
            newFieldDefList.add(UploadUtil.ANSWERS_FIELD_DEF);
            addSurveySchemaMetadata(oldSchema, survey);
            oldSchema.setFieldDefinitions(newFieldDefList);
            return updateSchemaRevisionV4(appId, schemaId, oldSchema.getRevision(), oldSchema);
        }
        // Answers field needs to be either
        // (a) an attachment (Large Text or normal)
        // (b) a string with isUnboundedLength=true
        UploadFieldType fieldType = answersFieldDef.getType();
        if (fieldType == UploadFieldType.LARGE_TEXT_ATTACHMENT || UploadFieldType.ATTACHMENT_TYPE_SET.contains(fieldType) || (UploadFieldType.STRING_TYPE_SET.contains(fieldType) && Boolean.TRUE.equals(answersFieldDef.isUnboundedText()))) {
            // The old schema works for the new survey. However, we want to ensure the old schema points to the
            // latest version of the survey. Update survey metadata in the schema.
            addSurveySchemaMetadata(oldSchema, survey);
            return updateSchemaRevisionV4(appId, schemaId, oldSchema.getRevision(), oldSchema);
        }
    // If execution gets this far, that means we have a schema with an "answers" field that's not compatible.
    // At this point, we go into the branch that creates a new schema, below.
    }
    // We were unable to reconcile this with the existing schema. Create a new schema. (Create API will
    // automatically bump the rev number if an old schema revision exists.)
    UploadSchema schemaToCreate = UploadSchema.create();
    addSurveySchemaMetadata(schemaToCreate, survey);
    schemaToCreate.setFieldDefinitions(ImmutableList.of(UploadUtil.ANSWERS_FIELD_DEF));
    return createSchemaRevisionV4(appId, schemaToCreate);
}
Also used : UploadFieldDefinition(org.sagebionetworks.bridge.models.upload.UploadFieldDefinition) UploadFieldType(org.sagebionetworks.bridge.models.upload.UploadFieldType) ArrayList(java.util.ArrayList) BadRequestException(org.sagebionetworks.bridge.exceptions.BadRequestException) UploadSchema(org.sagebionetworks.bridge.models.upload.UploadSchema)

Example 5 with UploadFieldDefinition

use of org.sagebionetworks.bridge.models.upload.UploadFieldDefinition in project BridgeServer2 by Sage-Bionetworks.

the class AppServiceTest method updateUploadMetadataCanAddAndReorderFields.

@Test
public void updateUploadMetadataCanAddAndReorderFields() {
    // make fields for test
    UploadFieldDefinition reorderedField1 = new UploadFieldDefinition.Builder().withName("reoredered-field-1").withType(UploadFieldType.INT).build();
    UploadFieldDefinition reorderedField2 = new UploadFieldDefinition.Builder().withName("reoredered-field-2").withType(UploadFieldType.BOOLEAN).build();
    UploadFieldDefinition addedField = new UploadFieldDefinition.Builder().withName("added-field").withType(UploadFieldType.TIMESTAMP).build();
    // old app
    App oldApp = getTestApp();
    oldApp.setUploadMetadataFieldDefinitions(ImmutableList.of(reorderedField1, reorderedField2));
    when(mockAppDao.getApp(TEST_APP_ID)).thenReturn(oldApp);
    // new app
    App newApp = getTestApp();
    newApp.setUploadMetadataFieldDefinitions(ImmutableList.of(reorderedField2, reorderedField1, addedField));
    // execute - no exception
    service.updateApp(newApp, true);
}
Also used : UploadFieldDefinition(org.sagebionetworks.bridge.models.upload.UploadFieldDefinition) DynamoApp(org.sagebionetworks.bridge.dynamodb.DynamoApp) App(org.sagebionetworks.bridge.models.apps.App) Test(org.testng.annotations.Test)

Aggregations

UploadFieldDefinition (org.sagebionetworks.bridge.models.upload.UploadFieldDefinition)66 Test (org.testng.annotations.Test)52 JsonNode (com.fasterxml.jackson.databind.JsonNode)32 File (java.io.File)17 UploadSchema (org.sagebionetworks.bridge.models.upload.UploadSchema)13 ObjectNode (com.fasterxml.jackson.databind.node.ObjectNode)9 ArrayList (java.util.ArrayList)9 Map (java.util.Map)8 HealthDataRecord (org.sagebionetworks.bridge.models.healthdata.HealthDataRecord)7 ImmutableMap (com.google.common.collect.ImmutableMap)6 UploadFieldType (org.sagebionetworks.bridge.models.upload.UploadFieldType)6 HashMap (java.util.HashMap)4 App (org.sagebionetworks.bridge.models.apps.App)4 DynamoApp (org.sagebionetworks.bridge.dynamodb.DynamoApp)3 DynamoUploadSchema (org.sagebionetworks.bridge.dynamodb.DynamoUploadSchema)3 BadRequestException (org.sagebionetworks.bridge.exceptions.BadRequestException)3 HealthDataSubmission (org.sagebionetworks.bridge.models.healthdata.HealthDataSubmission)3 ObjectMetadata (com.amazonaws.services.s3.model.ObjectMetadata)2 BigInteger (java.math.BigInteger)2 HashSet (java.util.HashSet)2