Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
cdd3d68
Initial work on refactor modeling skeleton
nickpalladino Apr 26, 2024
d8ca032
Added trials pending data to get existing step
nickpalladino Apr 29, 2024
77e4a7e
Addeed studies pending data to get existing step
nickpalladino Apr 29, 2024
65cf44d
Added locations pending data to get existing step
nickpalladino Apr 29, 2024
8633a3e
Added dataset pending data to get existing step
nickpalladino Apr 30, 2024
ab03644
Added germplasm pending data to get existing step
nickpalladino Apr 30, 2024
9d2e108
create Middleware class
dmeidlin May 1, 2024
d97f27c
add comensation methods to Middleware class
dmeidlin May 2, 2024
3a0481f
add compensate method to middleware
dmeidlin May 2, 2024
2741485
Work on breaking out common workflow code
nickpalladino May 2, 2024
5fb31a0
Merge branch 'experiment-processor-refactor' of https://github.com/Br…
nickpalladino May 2, 2024
8f761ae
create ExpUnitContextService
dmeidlin May 2, 2024
8fe5fe2
add mapPendingOUsByName service method
dmeidlin May 2, 2024
6be417a
add common methods
dmeidlin May 2, 2024
82d02e6
add service methods for getting existing brapi data
dmeidlin May 3, 2024
1ca976d
add overloaded trial methods for fetching trial pio
dmeidlin May 3, 2024
b4906a5
add pending data context to signature
dmeidlin May 3, 2024
8f15d08
add ValidateService
dmeidlin May 3, 2024
63091c3
add ValidateService#validateFields
dmeidlin May 3, 2024
8a89c53
add observation and statistics service
dmeidlin May 3, 2024
42b1482
update Middleware#link to handle nested middleware
dmeidlin May 6, 2024
7ca5817
add method to create new brapi trials for import
dmeidlin May 6, 2024
afc5e91
add method to update pending trials
dmeidlin May 6, 2024
c926da4
add methods for creating and updating pending datasets
dmeidlin May 6, 2024
6ae624e
add method to update brapi study dependencies
dmeidlin May 6, 2024
314d0b1
Added db migration to create workflows
nickpalladino May 6, 2024
17ec461
add methods for committing studies
dmeidlin May 6, 2024
968e9ba
add methods for committing obs units
dmeidlin May 6, 2024
70d268c
add methods for committing pending observations
dmeidlin May 6, 2024
8fc2f31
Added bean mapping for factory producing appropriate workflow
nickpalladino May 7, 2024
4b61708
Added endpoint for retrieving workflows for given mapping id
nickpalladino May 7, 2024
585947e
fix up middleware for refID validation
dmeidlin May 7, 2024
6d56b6e
add error handler middleware
dmeidlin May 7, 2024
c1fe8fa
Simplify record mapping
nickpalladino May 7, 2024
6953727
add ExistingObsUnit middleware
dmeidlin May 8, 2024
255eb25
refactor unit service methods and document
dmeidlin May 8, 2024
251d0ae
get trials for required exp units
dmeidlin May 8, 2024
4b8960b
make required studies middleware
dmeidlin May 8, 2024
71c145e
create required locations middleware
dmeidlin May 8, 2024
5635dcf
add required dataset middleware
dmeidlin May 9, 2024
b0198f0
create required germplasm middleware
dmeidlin May 9, 2024
61c1229
batch location request
dmeidlin May 9, 2024
c697622
batch requests for studies and trials
dmeidlin May 10, 2024
3ca1a30
Pass workflow id through to import services
nickpalladino May 10, 2024
7108089
make link method static
dmeidlin May 10, 2024
c8e0bfe
Add workflow factory to create workflows from ids
nickpalladino May 13, 2024
4391479
Add missing file header
nickpalladino May 13, 2024
87ffdb5
Add bean to import mapping workflow model
nickpalladino May 13, 2024
19e3f17
validate dynamic columns
dmeidlin May 13, 2024
964c2f3
hash observations and add map to context
dmeidlin May 14, 2024
186ee1d
add logging statement
dmeidlin May 14, 2024
dc2ea96
fix for loop
dmeidlin May 14, 2024
1c1df39
Added position column to workflows for explicit ordering
nickpalladino May 14, 2024
36944a5
Added additional workflow skeletons
nickpalladino May 14, 2024
7a9af10
Clean up factory code
nickpalladino May 14, 2024
027855f
construct pending observations
dmeidlin May 15, 2024
579e76d
Merge branch 'feature/BI-2122' into experiment-processor-refactor
nickpalladino May 15, 2024
d6ed109
cosntruct mapped pending import rows
dmeidlin May 17, 2024
7cb1f58
validate and record changelog
dmeidlin May 17, 2024
9ec7de2
create classes for processed data
dmeidlin May 21, 2024
92af469
create validator classes
dmeidlin May 21, 2024
99b17e2
use field validator
dmeidlin May 21, 2024
9141e9b
create preview statistics class
dmeidlin May 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package org.breedinginsight.api.model.v1.response;

import io.micronaut.http.HttpStatus;
import lombok.*;
import lombok.experimental.Accessors;

Expand Down Expand Up @@ -46,7 +47,6 @@ public void addError(Integer rowNumber, ValidationError validationError){
newRow.addError(validationError);
rowErrors.add(newRow);
}

public void merge(ValidationErrors validationErrors){
for (RowValidationErrors rowValidationErrors: validationErrors.getRowErrors()){
for (ValidationError validationError: rowValidationErrors.getErrors()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.breedinginsight.api.model.v1.response.metadata.StatusCode;
import org.breedinginsight.api.v1.controller.metadata.AddMetadata;
import org.breedinginsight.brapps.importer.model.mapping.ImportMapping;
import org.breedinginsight.brapps.importer.model.workflow.ImportMappingWorkflow;
import org.breedinginsight.brapps.importer.services.ImportConfigManager;
import org.breedinginsight.brapps.importer.model.config.ImportConfigResponse;
import org.breedinginsight.brapps.importer.services.FileImportService;
Expand Down Expand Up @@ -208,4 +209,21 @@ public HttpResponse<Response<DataResponse<ImportMapping>>> getSystemMappings(@Nu
Response<DataResponse<ImportMapping>> response = new Response(metadata, new DataResponse<>(result));
return HttpResponse.ok(response);
}

@Get("/import/mappings/{mappingId}/workflows")
@Produces(MediaType.APPLICATION_JSON)
@AddMetadata
@Secured(SecurityRule.IS_ANONYMOUS)
public HttpResponse<Response<DataResponse<ImportMappingWorkflow>>> getWorkflowsForSystemMapping(@PathVariable UUID mappingId) {

List<ImportMappingWorkflow> workflows = fileImportService.getWorkflowsForSystemMapping(mappingId);

List<Status> metadataStatus = new ArrayList<>();
metadataStatus.add(new Status(StatusCode.INFO, "Successful Query"));
Pagination pagination = new Pagination(workflows.size(), workflows.size(), 1, 0);
Metadata metadata = new Metadata(pagination, metadataStatus);

Response<DataResponse<ImportMappingWorkflow>> response = new Response(metadata, new DataResponse<>(workflows));
return HttpResponse.ok(response);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public HttpResponse<Response<ImportResponse>> commitData(@PathVariable UUID prog
@PathVariable UUID uploadId, @Body @Nullable Map<String, Object> userInput) {
try {
AuthenticatedUser actingUser = securityService.getUser();
ImportResponse result = fileImportService.updateUpload(programId, uploadId, actingUser, userInput, true);
ImportResponse result = fileImportService.updateUpload(programId, uploadId, null, actingUser, userInput, true);
Response<ImportResponse> response = new Response(result);
return HttpResponse.ok(response).status(HttpStatus.ACCEPTED);
} catch (DoesNotExistException e) {
Expand All @@ -140,7 +140,60 @@ public HttpResponse<Response<ImportResponse>> previewData(@PathVariable UUID pro
@PathVariable UUID uploadId) {
try {
AuthenticatedUser actingUser = securityService.getUser();
ImportResponse result = fileImportService.updateUpload(programId, uploadId, actingUser, null, false);
ImportResponse result = fileImportService.updateUpload(programId, uploadId, null, actingUser, null, false);
Response<ImportResponse> response = new Response(result);
return HttpResponse.ok(response).status(HttpStatus.ACCEPTED);
} catch (DoesNotExistException e) {
log.error(e.getMessage(), e);
return HttpResponse.notFound();
} catch (AuthorizationException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(HttpStatus.FORBIDDEN, e.getMessage());
} catch (UnprocessableEntityException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY, e.getMessage());
} catch (HttpStatusException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(e.getStatus(), e.getMessage());
}
}

@Put("programs/{programId}/import/mappings/{mappingId}/workflows/{workflowId}/data/{uploadId}/preview")
@Produces(MediaType.APPLICATION_JSON)
@AddMetadata
@ProgramSecured(roles = {ProgramSecuredRole.BREEDER, ProgramSecuredRole.SYSTEM_ADMIN})
public HttpResponse<Response<ImportResponse>> previewData(@PathVariable UUID programId, @PathVariable UUID mappingId,
@PathVariable UUID workflowId, @PathVariable UUID uploadId) {
try {
AuthenticatedUser actingUser = securityService.getUser();
ImportResponse result = fileImportService.updateUpload(programId, uploadId, workflowId, actingUser, null, false);
Response<ImportResponse> response = new Response(result);
return HttpResponse.ok(response).status(HttpStatus.ACCEPTED);
} catch (DoesNotExistException e) {
log.error(e.getMessage(), e);
return HttpResponse.notFound();
} catch (AuthorizationException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(HttpStatus.FORBIDDEN, e.getMessage());
} catch (UnprocessableEntityException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY, e.getMessage());
} catch (HttpStatusException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(e.getStatus(), e.getMessage());
}
}

@Put("programs/{programId}/import/mappings/{mappingId}/workflows/{workflowId}/data/{uploadId}/commit")
@Produces(MediaType.APPLICATION_JSON)
@AddMetadata
@ProgramSecured(roles = {ProgramSecuredRole.BREEDER, ProgramSecuredRole.SYSTEM_ADMIN})
public HttpResponse<Response<ImportResponse>> commitData(@PathVariable UUID programId, @PathVariable UUID mappingId,
@PathVariable UUID workflowId, @PathVariable UUID uploadId,
@Body @Nullable Map<String, Object> userInput) {
try {
AuthenticatedUser actingUser = securityService.getUser();
ImportResponse result = fileImportService.updateUpload(programId, uploadId, workflowId, actingUser, userInput, true);
Response<ImportResponse> response = new Response(result);
return HttpResponse.ok(response).status(HttpStatus.ACCEPTED);
} catch (DoesNotExistException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.breedinginsight.brapps.importer.daos;

import org.breedinginsight.brapps.importer.model.workflow.ImportMappingWorkflow;
import org.breedinginsight.dao.db.tables.daos.ImporterMappingWorkflowDao;
import org.jooq.Configuration;
import org.jooq.DSLContext;

import javax.inject.Inject;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

import static org.breedinginsight.dao.db.Tables.*;

public class ImportMappingWorkflowDAO extends ImporterMappingWorkflowDao {

private DSLContext dsl;

@Inject
public ImportMappingWorkflowDAO(Configuration config, DSLContext dsl) {
super(config);
this.dsl = dsl;
}

/**
* Retrieves a list of ImportMappingWorkflow objects associated with the given mappingId. They are ordered by
* position for proper ordering on the front end.
*
* @param mappingId The UUID of the mapping to retrieve the workflows for.
* @return A list of ImportMappingWorkflow objects.
*/
public List<ImportMappingWorkflow> getWorkflowsByImportMappingId(UUID mappingId) {
return dsl.select()
.from(IMPORTER_MAPPING_WORKFLOW)
.where(IMPORTER_MAPPING_WORKFLOW.MAPPING_ID.eq(mappingId))
.orderBy(IMPORTER_MAPPING_WORKFLOW.POSITION.asc())
.fetch(ImportMappingWorkflow::parseSQLRecord);
}

/**
* Retrieves a workflow by its ID.
*
* @param workflowId The ID of the workflow to retrieve.
* @return An Optional containing the ImportMappingWorkflow if found, otherwise an empty Optional.
*/
public Optional<ImportMappingWorkflow> getWorkflowById(UUID workflowId) {
return Optional.ofNullable(fetchOneById(workflowId))
.map(ImportMappingWorkflow::new);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,7 @@

package org.breedinginsight.brapps.importer.model.imports;

import org.brapi.client.v2.model.exceptions.ApiException;
import org.breedinginsight.brapps.importer.model.ImportUpload;
import org.breedinginsight.brapps.importer.model.response.ImportPreviewResponse;
import org.breedinginsight.model.Program;
import org.breedinginsight.model.User;
import org.breedinginsight.services.exceptions.DoesNotExistException;
import org.breedinginsight.services.exceptions.MissingRequiredInfoException;
import org.breedinginsight.services.exceptions.UnprocessableEntityException;
import org.breedinginsight.services.exceptions.ValidatorException;
import tech.tablesaw.api.Table;

import java.util.List;

public interface BrAPIImportService {
String getImportTypeId();
Expand All @@ -48,6 +37,6 @@ default String getMissingUserInputMsg(String fieldName) {
default String getWrongUserInputDataTypeMsg(String fieldName, String typeName) {
return String.format("User input, \"%s\" must be an %s", fieldName, typeName);
}
ImportPreviewResponse process(List<BrAPIImport> brAPIImports, Table data, Program program, ImportUpload upload, User user, Boolean commit)
ImportPreviewResponse process(ImportServiceContext context)
throws Exception;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.breedinginsight.brapps.importer.model.imports;

import lombok.*;
import org.breedinginsight.brapps.importer.model.ImportUpload;
import org.breedinginsight.brapps.importer.model.workflow.Workflow;
import org.breedinginsight.model.Program;
import org.breedinginsight.model.User;
import tech.tablesaw.api.Table;
import java.util.List;

@Getter
@Setter
@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class ImportServiceContext {
private Workflow workflow;
private List<BrAPIImport> brAPIImports;
private Table data;
private Program program;
private ImportUpload upload;
private User user;
private boolean commit;
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.breedinginsight.brapps.importer.model.ImportUpload;
import org.breedinginsight.brapps.importer.model.imports.BrAPIImport;
import org.breedinginsight.brapps.importer.model.imports.BrAPIImportService;
import org.breedinginsight.brapps.importer.model.imports.ImportServiceContext;
import org.breedinginsight.brapps.importer.model.response.ImportPreviewResponse;
import org.breedinginsight.brapps.importer.services.processors.ExperimentProcessor;
import org.breedinginsight.brapps.importer.services.processors.Processor;
Expand Down Expand Up @@ -66,12 +67,24 @@ public String getMissingColumnMsg(String columnName) {
}

@Override
public ImportPreviewResponse process(List<BrAPIImport> brAPIImports, Table data, Program program, ImportUpload upload, User user, Boolean commit)
public ImportPreviewResponse process(ImportServiceContext context)
throws Exception {

ImportPreviewResponse response = null;
List<Processor> processors = List.of(experimentProcessorProvider.get());
response = processorManagerProvider.get().process(brAPIImports, processors, data, program, upload, user, commit);

if (context.getWorkflow() != null) {
log.info("Workflow: " + context.getWorkflow().getName());
}

// TODO: change to calling workflow process instead of processor manager
response = processorManagerProvider.get().process(context.getBrAPIImports(),
processors,
context.getData(),
context.getProgram(),
context.getUpload(),
context.getUser(),
context.isCommit());
return response;

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.breedinginsight.brapps.importer.model.ImportUpload;
import org.breedinginsight.brapps.importer.model.imports.BrAPIImport;
import org.breedinginsight.brapps.importer.model.imports.BrAPIImportService;
import org.breedinginsight.brapps.importer.model.imports.ImportServiceContext;
import org.breedinginsight.brapps.importer.model.response.ImportPreviewResponse;
import org.breedinginsight.brapps.importer.services.processors.GermplasmProcessor;
import org.breedinginsight.brapps.importer.services.processors.Processor;
Expand Down Expand Up @@ -62,12 +63,18 @@ public String getImportTypeId() {
}

@Override
public ImportPreviewResponse process(List<BrAPIImport> brAPIImports, Table data, Program program, ImportUpload upload, User user, Boolean commit)
public ImportPreviewResponse process(ImportServiceContext context)
throws Exception {

ImportPreviewResponse response = null;
List<Processor> processors = List.of(germplasmProcessorProvider.get());
response = processorManagerProvider.get().process(brAPIImports, processors, data, program, upload, user, commit);
response = processorManagerProvider.get().process(context.getBrAPIImports(),
processors,
context.getData(),
context.getProgram(),
context.getUpload(),
context.getUser(),
context.isCommit());
return response;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.breedinginsight.brapps.importer.model.ImportUpload;
import org.breedinginsight.brapps.importer.model.imports.BrAPIImport;
import org.breedinginsight.brapps.importer.model.imports.BrAPIImportService;
import org.breedinginsight.brapps.importer.model.imports.ImportServiceContext;
import org.breedinginsight.brapps.importer.model.response.ImportPreviewResponse;
import org.breedinginsight.brapps.importer.services.processors.Processor;
import org.breedinginsight.brapps.importer.services.processors.ProcessorManager;
Expand Down Expand Up @@ -59,13 +60,14 @@ public BrAPIImport getImportClass() {
}

@Override
public ImportPreviewResponse process(List<BrAPIImport> brAPIImports,
Table data,
Program program,
ImportUpload upload,
User user,
Boolean commit) throws Exception {
public ImportPreviewResponse process(ImportServiceContext context) throws Exception {
List<Processor> processors = List.of(sampleProcessorProvider.get());
return processorManagerProvider.get().process(brAPIImports, processors, data, program, upload, user, commit);
return processorManagerProvider.get().process(context.getBrAPIImports(),
processors,
context.getData(),
context.getProgram(),
context.getUpload(),
context.getUser(),
context.isCommit());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.breedinginsight.brapps.importer.model.workflow;

import lombok.*;
import org.breedinginsight.brapps.importer.model.ImportUpload;
import org.breedinginsight.brapps.importer.model.imports.BrAPIImport;
import org.breedinginsight.brapps.importer.model.imports.PendingImport;
import org.breedinginsight.model.Program;
import org.breedinginsight.model.User;
import tech.tablesaw.api.Table;

import java.util.List;
import java.util.Map;
import java.util.UUID;

@Getter
@Setter
@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class ImportContext {
private UUID workflowId;
private ImportUpload upload;
private List<BrAPIImport> importRows;
private Map<Integer, PendingImport> mappedBrAPIImport;
private Table data;
private Program program;
private User user;
private boolean commit;
}
Loading