Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
314d0b1
Added db migration to create workflows
nickpalladino 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
c1fe8fa
Simplify record mapping
nickpalladino May 7, 2024
3ca1a30
Pass workflow id through to import services
nickpalladino 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
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
09b9133
Merge branch 'develop' into feature/BI-2122
nickpalladino May 15, 2024
0585568
Moved create workflow work to own branch and rearranged things a little
nickpalladino May 20, 2024
777b7e2
Added file headers and dynamic column parser
nickpalladino May 20, 2024
5564ca1
create micronaut composite pattern classes for experiment import work…
dmeidlin May 22, 2024
f726611
create FileImportService method for GET workflows
dmeidlin May 22, 2024
f6952dd
delete unused classes
dmeidlin May 22, 2024
5e31aa6
clean up and renaming
dmeidlin May 23, 2024
708793d
add overrides to import services
dmeidlin May 23, 2024
68bdacb
create ExperimentWorkflow interface that extends Workflow interface
dmeidlin May 23, 2024
0e022f1
create interfaces for germplasm and sample workflows
dmeidlin May 23, 2024
f2a1034
create interfaces
dmeidlin May 23, 2024
402eb5d
create DomainImportService abstract class
dmeidlin May 31, 2024
c5dd139
Shared services work in progress
nickpalladino Jun 3, 2024
8825462
Renamed common services
nickpalladino Jun 10, 2024
2b0256d
Simplified workflow step calling
nickpalladino Jun 10, 2024
bce2c7f
change Workflow field names
dmeidlin Jun 10, 2024
6060fcc
use processorManager until Workflow business logic in place
dmeidlin Jun 10, 2024
90f478b
fix workflow navigator injection
dmeidlin Jun 10, 2024
62cf9ac
set the order field for workflows
dmeidlin Jun 10, 2024
57f5cfb
fix npe
dmeidlin Jun 10, 2024
d21a988
Merge pull request #360 from Breeding-Insight/feature/BI-2122-A
dmeidlin Jun 11, 2024
644ca0c
Added commit step
nickpalladino Jun 12, 2024
c8d1cb6
Building
nickpalladino Jun 14, 2024
d57e4ac
Renamed to have github actions run
nickpalladino Jun 14, 2024
e406e38
Merge branch 'feature/BI-2122' into feature/BI-2132-A
nickpalladino Jun 18, 2024
79189ba
Messing with dependency issue
nickpalladino Jun 18, 2024
0ef8cd5
Removed ununsed fileImportService injection and resolved DI issue
nickpalladino Jun 21, 2024
1acd04b
Added in BI-2128 change
nickpalladino Jun 21, 2024
fc2a661
Merge branch 'develop' into feature/BI-2132-A
nickpalladino Jun 21, 2024
6a4043d
Updated create only tests to use create workflow
nickpalladino Jun 21, 2024
651cffc
Removed unused migration
nickpalladino Jun 21, 2024
39fb8cd
Removed append environment workflow
nickpalladino Jun 21, 2024
be8ea38
Fix error message
nickpalladino Jun 21, 2024
d11ef3c
Removed navigator stuff handled in domain import service
nickpalladino Jun 21, 2024
eebb493
Removed some development comments
nickpalladino Jun 21, 2024
b5dc3e8
Reference enum for new-experiment
nickpalladino Jul 1, 2024
2bbf7f3
Change variable name to reflect string type
nickpalladino Jul 1, 2024
ccc1414
Clarified comment
nickpalladino Jul 1, 2024
7a35165
Clarified comment
nickpalladino Jul 1, 2024
aa06c6e
Removed old comment
nickpalladino Jul 1, 2024
dd6f348
Updated doc comment
nickpalladino Jul 1, 2024
a6c3590
Cleaned up ProcessedData code
nickpalladino Jul 1, 2024
1a6de32
Changed from workflow to workflowId
nickpalladino Jul 2, 2024
a488612
Change exception handling
nickpalladino Jul 2, 2024
9b04d44
Merge branch 'develop' into feature/BI-2132-A
nickpalladino Jul 2, 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 @@ -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.ImportWorkflow;
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,27 @@ 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<ImportWorkflow>>> getWorkflowsForSystemMapping(@PathVariable UUID mappingId) throws Exception {

List<ImportWorkflow> workflows = null;
try {
workflows = fileImportService.getWorkflowsForSystemMapping(mappingId);
} catch (DoesNotExistException e) {
log.error(e.getMessage(), e);
return HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY, e.getMessage());
}

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<ImportWorkflow>> 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 String 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 String 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
Expand Up @@ -17,22 +17,15 @@

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 org.breedinginsight.brapps.importer.model.workflow.ImportWorkflow;

import java.util.List;

public interface BrAPIImportService {
String getImportTypeId();
BrAPIImport getImportClass();
List<ImportWorkflow> getWorkflows() throws Exception;
default String getInvalidIntegerMsg(String columnName) {
return String.format("Column name \"%s\" must be integer type, but non-integer type provided.", columnName);
}
Expand All @@ -48,6 +41,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,96 @@
/*
* 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.extern.slf4j.Slf4j;
import org.breedinginsight.brapps.importer.model.imports.experimentObservation.ExperimentObservation;
import org.breedinginsight.brapps.importer.model.response.ImportPreviewResponse;
import org.breedinginsight.brapps.importer.model.workflow.ExperimentWorkflow;
import org.breedinginsight.brapps.importer.model.workflow.ImportWorkflow;
import org.breedinginsight.brapps.importer.model.workflow.ImportWorkflowResult;
import org.breedinginsight.brapps.importer.model.workflow.Workflow;
import org.breedinginsight.brapps.importer.services.processors.ExperimentProcessor;
import org.breedinginsight.brapps.importer.services.processors.ProcessorManager;
import org.breedinginsight.brapps.importer.services.processors.experiment.ExperimentWorkflowNavigator;

import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import java.util.List;
import java.util.Optional;

@Singleton
@Slf4j
public abstract class DomainImportService implements BrAPIImportService {

// TODO: delete processor fields once WorkflowNavigator is used
private final Provider<ExperimentProcessor> experimentProcessorProvider;
private final Provider<ProcessorManager> processorManagerProvider;
private final Workflow workflowNavigator;


public DomainImportService(Provider<ExperimentProcessor> experimentProcessorProvider,
Provider<ProcessorManager> processorManagerProvider,
Workflow workflowNavigator)
{
this.experimentProcessorProvider = experimentProcessorProvider;
this.processorManagerProvider = processorManagerProvider;
this.workflowNavigator = workflowNavigator;
}

@Override
public String getMissingColumnMsg(String columnName) {
return "Column heading does not match template or ontology";
}
@Override
public List<ImportWorkflow> getWorkflows() throws Exception{
return workflowNavigator.getWorkflows();
}

@Override
public ImportPreviewResponse process(ImportServiceContext context)
throws Exception {

Optional.ofNullable(context.getWorkflowId())
.filter(workflowId -> !workflowId.isEmpty())
.ifPresent(workflowId -> log.info("Workflow: " + workflowId));

// TODO: return results from WorkflowNavigator once processing logic is in separate workflows
// return workflowNavigator.process(context).flatMap(ImportWorkflowResult::getImportPreviewResponse).orElse(null);
if (ExperimentWorkflowNavigator.Workflow.NEW_OBSERVATION.getId().equals(context.getWorkflowId())) {
Optional<ImportWorkflowResult> result = workflowNavigator.process(context);

// Throw any exceptions caught during workflow processing
if (result.flatMap(ImportWorkflowResult::getCaughtException).isPresent()) {
throw result.flatMap(ImportWorkflowResult::getCaughtException).get();
}

return result.flatMap(ImportWorkflowResult::getImportPreviewResponse).orElse(null);

} else {
return processorManagerProvider.get().process(context.getBrAPIImports(),
List.of(experimentProcessorProvider.get()),
context.getData(),
context.getProgram(),
context.getUpload(),
context.getUser(),
context.isCommit());
}
}
}

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.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 String workflowId;
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 @@ -18,36 +18,28 @@
package org.breedinginsight.brapps.importer.model.imports.experimentObservation;

import lombok.extern.slf4j.Slf4j;
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.response.ImportPreviewResponse;
import org.breedinginsight.brapps.importer.model.imports.DomainImportService;
import org.breedinginsight.brapps.importer.services.processors.ExperimentProcessor;
import org.breedinginsight.brapps.importer.services.processors.Processor;
import org.breedinginsight.brapps.importer.services.processors.ProcessorManager;
import org.breedinginsight.model.Program;
import org.breedinginsight.model.User;
import tech.tablesaw.api.Table;
import org.breedinginsight.brapps.importer.services.processors.experiment.ExperimentWorkflowNavigator;

import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import java.util.List;

@Singleton
@Slf4j
public class ExperimentImportService implements BrAPIImportService {
public class ExperimentImportService extends DomainImportService {

private final String IMPORT_TYPE_ID = "ExperimentImport";

private final Provider<ExperimentProcessor> experimentProcessorProvider;
private final Provider<ProcessorManager> processorManagerProvider;

// TODO: delete processor fields once WorkflowNavigator is used
@Inject
public ExperimentImportService(Provider<ExperimentProcessor> experimentProcessorProvider, Provider<ProcessorManager> processorManagerProvider)
public ExperimentImportService(Provider<ExperimentProcessor> experimentProcessorProvider,
Provider<ProcessorManager> processorManagerProvider,
ExperimentWorkflowNavigator workflowNavigator)
{
this.experimentProcessorProvider = experimentProcessorProvider;
this.processorManagerProvider = processorManagerProvider;
super(experimentProcessorProvider, processorManagerProvider, workflowNavigator);
}
Comment on lines +36 to 43
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I merged into BI-2134 the changes from BI-2132 for ExperimentFileImportTest and was able to implement this TODO. So, there isn't any additional work required, you can just accept the changes during the merge.


@Override
Expand All @@ -60,20 +52,5 @@ public String getImportTypeId() {
return IMPORT_TYPE_ID;
}

@Override
public String getMissingColumnMsg(String columnName) {
return "Column heading does not match template or ontology";
}

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

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

}
}

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
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.model.workflow.ImportWorkflow;
import org.breedinginsight.brapps.importer.services.processors.GermplasmProcessor;
import org.breedinginsight.brapps.importer.services.processors.Processor;
import org.breedinginsight.brapps.importer.services.processors.ProcessorManager;
Expand All @@ -32,6 +34,7 @@
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;

@Singleton
Expand All @@ -56,18 +59,29 @@ public GermplasmImport getImportClass() {
return new GermplasmImport();
}

@Override
public List<ImportWorkflow> getWorkflows() {
return new ArrayList<>();
}

@Override
public String getImportTypeId() {
return IMPORT_TYPE_ID;
}

@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;
}
}
Loading