Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 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
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
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
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) {

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/{workflow}/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 workflow, @PathVariable UUID uploadId) {
try {
AuthenticatedUser actingUser = securityService.getUser();
ImportResponse result = fileImportService.updateUpload(programId, uploadId, workflow, 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/{workflow}/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 workflow, @PathVariable UUID uploadId,
@Body @Nullable Map<String, Object> userInput) {
try {
AuthenticatedUser actingUser = securityService.getUser();
ImportResponse result = fileImportService.updateUpload(programId, uploadId, workflow, 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();
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,82 @@
/*
* 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.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;

@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() {
return workflowNavigator.getWorkflows();
}

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

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

// TODO: return results from WorkflowNavigator once processing logic is in separate workflows
// return workflowNavigator.process(context).flatMap(ImportWorkflowResult::getImportPreviewResponse).orElse(null);
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 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 @@ -18,16 +18,15 @@
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.imports.DomainImportService;
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.model.workflow.Workflow;
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;
Expand All @@ -36,18 +35,17 @@

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

@Override
Expand All @@ -60,20 +58,6 @@ 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