diff --git a/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/create/workflow/CreateNewExperimentWorkflow.java b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/create/workflow/CreateNewExperimentWorkflow.java index 010a14095..a6b6ea8b9 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/create/workflow/CreateNewExperimentWorkflow.java +++ b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/create/workflow/CreateNewExperimentWorkflow.java @@ -17,11 +17,9 @@ package org.breedinginsight.brapps.importer.services.processors.experiment.create.workflow; -import io.micronaut.context.annotation.Prototype; import io.micronaut.http.HttpStatus; import io.micronaut.http.exceptions.HttpStatusException; import lombok.extern.slf4j.Slf4j; -import lombok.val; import org.apache.commons.lang3.StringUtils; import org.brapi.v2.model.pheno.BrAPIObservation; import org.breedinginsight.api.model.v1.response.ValidationErrors; @@ -35,7 +33,6 @@ import org.breedinginsight.brapps.importer.model.response.PendingImportObject; import org.breedinginsight.brapps.importer.model.workflow.ImportContext; import org.breedinginsight.brapps.importer.model.workflow.ProcessedData; -import org.breedinginsight.brapps.importer.model.workflow.Workflow; import org.breedinginsight.brapps.importer.services.ImportStatusService; import org.breedinginsight.brapps.importer.services.processors.experiment.ExperimentUtilities; import org.breedinginsight.brapps.importer.services.processors.experiment.create.model.PendingData; @@ -49,7 +46,6 @@ import org.breedinginsight.services.exceptions.ValidatorException; import javax.inject.Inject; -import javax.inject.Named; import java.util.*; import lombok.Getter; @@ -106,8 +102,7 @@ private ImportPreviewResponse runWorkflow(ImportContext context) throws Exceptio statusService.updateMessage(upload, "Checking existing experiment objects in brapi service and mapping data"); ProcessedPhenotypeData phenotypeData = experimentPhenotypeService.extractPhenotypes(context); - // TODO: eliminate or modify unnecessary populateExistingPIO step as it relies on the user supplying existing observation unit ids - ProcessContext processContext = populateExistingPendingImportObjectsStep.process(context, phenotypeData); + ProcessContext processContext = populateExistingPendingImportObjectsStep.process(context); populateNewPendingImportObjectsStep.process(processContext, phenotypeData); ValidationErrors validationErrors = validatePendingImportObjectsStep.process(context, processContext.getPendingData(), phenotypeData, processedData); diff --git a/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/create/workflow/steps/PopulateExistingPendingImportObjectsStep.java b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/create/workflow/steps/PopulateExistingPendingImportObjectsStep.java index e611ec46f..d7b6912f9 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/create/workflow/steps/PopulateExistingPendingImportObjectsStep.java +++ b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/create/workflow/steps/PopulateExistingPendingImportObjectsStep.java @@ -41,12 +41,10 @@ import org.breedinginsight.brapps.importer.services.processors.experiment.ExperimentUtilities; import org.breedinginsight.brapps.importer.services.processors.experiment.create.model.PendingData; import org.breedinginsight.brapps.importer.services.processors.experiment.create.model.ProcessContext; -import org.breedinginsight.brapps.importer.services.processors.experiment.create.model.ProcessedPhenotypeData; import org.breedinginsight.brapps.importer.services.processors.experiment.services.ExperimentStudyService; import org.breedinginsight.brapps.importer.services.processors.experiment.services.ExperimentTrialService; import org.breedinginsight.model.Program; import org.breedinginsight.model.ProgramLocation; -import org.breedinginsight.model.Trait; import org.breedinginsight.services.ProgramLocationService; import org.breedinginsight.utilities.DatasetUtil; import org.breedinginsight.utilities.Utilities; @@ -65,13 +63,10 @@ @Slf4j public class PopulateExistingPendingImportObjectsStep { - private final BrAPIObservationUnitDAO brAPIObservationUnitDAO; - private final BrAPITrialDAO brAPITrialDAO; private final BrAPIStudyDAO brAPIStudyDAO; private final ProgramLocationService locationService; private final BrAPIListDAO brAPIListDAO; private final BrAPIGermplasmDAO brAPIGermplasmDAO; - private final BrAPIObservationDAO brAPIObservationDAO; private final ExperimentStudyService experimentStudyService; private final ExperimentTrialService experimentTrialService; @@ -79,40 +74,38 @@ public class PopulateExistingPendingImportObjectsStep { private String BRAPI_REFERENCE_SOURCE; @Inject - public PopulateExistingPendingImportObjectsStep(BrAPIObservationUnitDAO brAPIObservationUnitDAO, - BrAPITrialDAO brAPITrialDAO, + public PopulateExistingPendingImportObjectsStep( BrAPIStudyDAO brAPIStudyDAO, ProgramLocationService locationService, BrAPIListDAO brAPIListDAO, BrAPIGermplasmDAO brAPIGermplasmDAO, - BrAPIObservationDAO brAPIObservationDAO, ExperimentStudyService experimentStudyService, ExperimentTrialService experimentTrialService) { - this.brAPIObservationUnitDAO = brAPIObservationUnitDAO; - this.brAPITrialDAO = brAPITrialDAO; this.brAPIStudyDAO = brAPIStudyDAO; this.locationService = locationService; this.brAPIListDAO = brAPIListDAO; this.brAPIGermplasmDAO = brAPIGermplasmDAO; - this.brAPIObservationDAO = brAPIObservationDAO; this.experimentStudyService = experimentStudyService; this.experimentTrialService = experimentTrialService; } - public ProcessContext process(ImportContext input, ProcessedPhenotypeData phenotypeData) { + public ProcessContext process(ImportContext input) { List experimentImportRows = ExperimentUtilities.importRowsToExperimentObservations(input.getImportRows()); Program program = input.getProgram(); // Populate pending objects with existing status - Map> observationUnitByNameNoScope = initializeObservationUnits(program, experimentImportRows); - Map> trialByNameNoScope = experimentTrialService.initializeTrialByNameNoScope(program, observationUnitByNameNoScope, experimentImportRows); - Map> studyByNameNoScope = initializeStudyByNameNoScope(program, trialByNameNoScope, observationUnitByNameNoScope, experimentImportRows); + Map> observationUnitByNameNoScope = new HashMap<>(); + Map> trialByNameNoScope = experimentTrialService.initializeTrialByNameNoScope(program, experimentImportRows); + Map> studyByNameNoScope =initializeStudyByNameNoScope(program, trialByNameNoScope, experimentImportRows); + // interesting we're using our data model instead of brapi for locations - Map> locationByName = initializeUniqueLocationNames(program, studyByNameNoScope, experimentImportRows); - Map> obsVarDatasetByName = initializeObsVarDatasetByName(program, trialByNameNoScope, experimentImportRows); - Map> existingGermplasmByGID = initializeExistingGermplasmByGID(program, observationUnitByNameNoScope, experimentImportRows); - Map existingObsByObsHash = fetchExistingObservations(phenotypeData.getReferencedTraits(), studyByNameNoScope, program); + Map> locationByName = initializeUniqueLocationNames(program, experimentImportRows); + Map> obsVarDatasetByName = initializeObsVarDatasetByName(program, experimentImportRows); + Map> existingGermplasmByGID = initializeExistingGermplasmByGID(program, experimentImportRows); + Map existingObsByObsHash = new HashMap<>(); + + PendingData existing = PendingData.builder() .observationUnitByNameNoScope(observationUnitByNameNoScope) @@ -131,116 +124,6 @@ public ProcessContext process(ImportContext input, ProcessedPhenotypeData phenot .build(); } - /** - * Initializes the observation units for the given program and experimentImportRows. - * - * @param program The program object - * @param experimentImportRows A list of ExperimentObservation objects - * @return A map of Observation Unit IDs to PendingImportObject objects - * - * @throws InternalServerException - * @throws IllegalStateException - */ - private Map> initializeObservationUnits(Program program, List experimentImportRows) { - Map> observationUnitByName = new HashMap<>(); - return observationUnitByName; - // TODO: change how ProcessContext is generated so it does not rely on this unused method -// Map rowByObsUnitId = new HashMap<>(); -// experimentImportRows.forEach(row -> { -// if (StringUtils.isNotBlank(row.getObsUnitID())) { -// if(rowByObsUnitId.containsKey(row.getObsUnitID())) { -// throw new IllegalStateException("ObsUnitId is repeated: " + row.getObsUnitID()); -// } -// rowByObsUnitId.put(row.getObsUnitID(), row); -// } -// }); -// -// try { -// List existingObsUnits = brAPIObservationUnitDAO.getObservationUnitsById(rowByObsUnitId.keySet(), program); -// -// // TODO: grab from externalReferences -// /* -// observationUnitByObsUnitId = existingObsUnits.stream() -// .collect(Collectors.toMap(BrAPIObservationUnit::getObservationUnitDbId, -// (BrAPIObservationUnit unit) -> new PendingImportObject<>(unit, false))); -// */ -// -// String refSource = String.format("%s/%s", BRAPI_REFERENCE_SOURCE, ExternalReferenceSource.OBSERVATION_UNITS.getName()); -// if (existingObsUnits.size() == rowByObsUnitId.size()) { -// existingObsUnits.forEach(brAPIObservationUnit -> { -// processAndCacheObservationUnit(brAPIObservationUnit, refSource, program, observationUnitByName, rowByObsUnitId); -// -// BrAPIExternalReference idRef = Utilities.getExternalReference(brAPIObservationUnit.getExternalReferences(), refSource) -// .orElseThrow(() -> new InternalServerException("An ObservationUnit ID was not found in any of the external references")); -// -// ExperimentObservation row = rowByObsUnitId.get(idRef.getReferenceId()); -// row.setExpTitle(Utilities.removeProgramKey(brAPIObservationUnit.getTrialName(), program.getKey())); -// row.setEnv(Utilities.removeProgramKeyAndUnknownAdditionalData(brAPIObservationUnit.getStudyName(), program.getKey())); -// row.setEnvLocation(Utilities.removeProgramKey(brAPIObservationUnit.getLocationName(), program.getKey())); -// }); -// } else { -// List missingIds = new ArrayList<>(rowByObsUnitId.keySet()); -// missingIds.removeAll(existingObsUnits.stream().map(BrAPIObservationUnit::getObservationUnitDbId).collect(Collectors.toList())); -// throw new IllegalStateException("Observation Units not found for ObsUnitId(s): " + String.join(ExperimentUtilities.COMMA_DELIMITER, missingIds)); -// } -// -// return observationUnitByName; -// } catch (ApiException e) { -// log.error("Error fetching observation units: " + Utilities.generateApiExceptionLogMessage(e), e); -// throw new InternalServerException(e.toString(), e); -// } - } - - /** - * Initializes studies by name without scope. - * - * @param program The program object. - * @param trialByNameNoScope A map of trial names with their corresponding pending import objects. - * @param experimentImportRows A list of experiment observation objects. - * @return A map of study names with their corresponding pending import objects. - * @throws InternalServerException If there is an error while processing the method. - */ - private Map> initializeStudyByNameNoScope(Program program, - Map> trialByNameNoScope, - Map> observationUnitByNameNoScope, - List experimentImportRows) { - Map> studyByName = new HashMap<>(); - if (trialByNameNoScope.size() != 1) { - return studyByName; - } - - try { - initializeStudiesForExistingObservationUnits(program, studyByName, observationUnitByNameNoScope); - } catch (ApiException e) { - log.error("Error fetching studies: " + Utilities.generateApiExceptionLogMessage(e), e); - throw new InternalServerException(e.toString(), e); - } catch (Exception e) { - log.error("Error processing studies", e); - throw new InternalServerException(e.toString(), e); - } - - List existingStudies; - Optional> trial = getTrialPIO(experimentImportRows, trialByNameNoScope); - - try { - if (trial.isEmpty()) { - // TODO: throw ValidatorException and return 422 - } - UUID experimentId = trial.get().getId(); - existingStudies = brAPIStudyDAO.getStudiesByExperimentID(experimentId, program); - for (BrAPIStudy existingStudy : existingStudies) { - experimentStudyService.processAndCacheStudy(existingStudy, program, BrAPIStudy::getStudyName, studyByName); - } - } catch (ApiException e) { - log.error("Error fetching studies: " + Utilities.generateApiExceptionLogMessage(e), e); - throw new InternalServerException(e.toString(), e); - } catch (Exception e) { - log.error("Error processing studies: ", e); - throw new InternalServerException(e.toString(), e); - } - - return studyByName; - } /** * Retrieves the PendingImportObject of a BrAPITrial based on the given list of ExperimentObservation and trialByNameNoScope map. @@ -266,52 +149,19 @@ private Optional> getTrialPIO(List> studyByName, - Map> observationUnitByNameNoScope - ) throws Exception { - Set studyDbIds = observationUnitByNameNoScope.values() - .stream() - .map(pio -> pio.getBrAPIObject() - .getStudyDbId()) - .collect(Collectors.toSet()); - - List studies = experimentStudyService.fetchStudiesByDbId(studyDbIds, program); - for (BrAPIStudy study : studies) { - experimentStudyService.processAndCacheStudy(study, program, BrAPIStudy::getStudyName, studyByName); - } - } - /** * Initializes unique location names for a program. * * @param program The program object. - * @param studyByNameNoScope A map of study names and corresponding BrAPI study objects. * @param experimentImportRows A list of experiment observation objects for import. * @return A map of location names and their corresponding pending import objects. * @throws InternalServerException If there is an error fetching locations. */ private Map> initializeUniqueLocationNames(Program program, - Map> studyByNameNoScope, List experimentImportRows) { Map> locationByName = new HashMap<>(); - List existingLocations = new ArrayList<>(); - if(studyByNameNoScope.size() > 0) { - Set locationDbIds = studyByNameNoScope.values() - .stream() - .map(study -> study.getBrAPIObject() - .getLocationDbId()) - .collect(Collectors.toSet()); - try { - existingLocations.addAll(locationService.getLocationsByDbId(locationDbIds, program.getId())); - } catch (ApiException e) { - log.error("Error fetching locations: " + Utilities.generateApiExceptionLogMessage(e), e); - throw new InternalServerException(e.toString(), e); - } - } + List existingLocations; List uniqueLocationNames = experimentImportRows.stream() .map(ExperimentObservation::getEnvLocation) @@ -320,7 +170,7 @@ private Map> initializeUniqueLocati .collect(Collectors.toList()); try { - existingLocations.addAll(locationService.getLocationsByName(uniqueLocationNames, program.getId())); + existingLocations = new ArrayList<>(locationService.getLocationsByName(uniqueLocationNames, program.getId())); } catch (ApiException e) { log.error("Error fetching locations: " + Utilities.generateApiExceptionLogMessage(e), e); throw new InternalServerException(e.toString(), e); @@ -329,21 +179,57 @@ private Map> initializeUniqueLocati existingLocations.forEach(existingLocation -> locationByName.put(existingLocation.getName(), new PendingImportObject<>(ImportObjectState.EXISTING, existingLocation, existingLocation.getId()))); return locationByName; } + /** + * Initializes studies by name without scope. + * + * @param program The program object. + * @param trialByNameNoScope A map of trial names with their corresponding pending import objects. + * @param experimentImportRows A list of experiment observation objects. + * @return A map of study names with their corresponding pending import objects. + * @throws InternalServerException If there is an error while processing the method. + */ + private Map> initializeStudyByNameNoScope(Program program, + Map> trialByNameNoScope, + List experimentImportRows) { + Map> studyByName = new HashMap<>(); + if (trialByNameNoScope.size() != 1) { + return studyByName; + } + + + List existingStudies; + Optional> trial = getTrialPIO(experimentImportRows, trialByNameNoScope); + + try { + // the 'trial' variable will never be "null". + UUID experimentId = trial.get().getId(); + existingStudies = brAPIStudyDAO.getStudiesByExperimentID(experimentId, program); + for (BrAPIStudy existingStudy : existingStudies) { + experimentStudyService.processAndCacheStudy(existingStudy, program, BrAPIStudy::getStudyName, studyByName); + } + } catch (ApiException e) { + log.error("Error fetching studies: " + Utilities.generateApiExceptionLogMessage(e), e); + throw new InternalServerException(e.toString(), e); + } catch (Exception e) { + log.error("Error processing studies: ", e); + throw new InternalServerException(e.toString(), e); + } + + return studyByName; + } /** * Initializes observation variable dataset by name. * * @param program The program associated with the dataset. - * @param trialByNameNoScope The map of trials identified by name without scope. * @param experimentImportRows The list of experiment observation rows. * @return The map of observation variable dataset indexed by name. * - * @throws InternalServerException */ private Map> initializeObsVarDatasetByName(Program program, - Map> trialByNameNoScope, List experimentImportRows) { Map> obsVarDatasetByName = new HashMap<>(); + Map> trialByNameNoScope = new HashMap<>(); Optional> trialPIO = getTrialPIO(experimentImportRows, trialByNameNoScope); @@ -374,13 +260,29 @@ private Map> initializeObsVarDatas return obsVarDatasetByName; } + private void initializeStudiesForExistingObservationUnits( + Program program, + Map> studyByName, + Map> observationUnitByNameNoScope + ) throws Exception { + Set studyDbIds = observationUnitByNameNoScope.values() + .stream() + .map(pio -> pio.getBrAPIObject() + .getStudyDbId()) + .collect(Collectors.toSet()); + + List studies = experimentStudyService.fetchStudiesByDbId(studyDbIds, program); + for (BrAPIStudy study : studies) { + experimentStudyService.processAndCacheStudy(study, program, BrAPIStudy::getStudyName, studyByName); + } + } + /** * Process and cache an object of type BrAPIListDetails. * * @param existingList The existing list to be processed and cached * @param obsVarDatasetByName A map of ObsVarDatasets indexed by name (will be modified in place) * - * @throws IllegalStateException */ private void processAndCacheObsVarDataset(BrAPIListDetails existingList, Map> obsVarDatasetByName) { BrAPIExternalReference xref = Utilities.getExternalReference(existingList.getExternalReferences(), @@ -394,27 +296,16 @@ private void processAndCacheObsVarDataset(BrAPIListDetails existingList, Map> initializeExistingGermplasmByGID(Program program, - Map> observationUnitByNameNoScope, List experimentImportRows) { Map> existingGermplasmByGID = new HashMap<>(); - List existingGermplasms = new ArrayList<>(); - if(observationUnitByNameNoScope.size() > 0) { - Set germplasmDbIds = observationUnitByNameNoScope.values().stream().map(ou -> ou.getBrAPIObject().getGermplasmDbId()).collect(Collectors.toSet()); - try { - existingGermplasms.addAll(brAPIGermplasmDAO.getGermplasmsByDBID(germplasmDbIds, program.getId())); - } catch (ApiException e) { - log.error("Error fetching germplasm: " + Utilities.generateApiExceptionLogMessage(e), e); - throw new InternalServerException(e.toString(), e); - } - } + List existingGermplasms; + List uniqueGermplasmGIDs = experimentImportRows.stream() .map(ExperimentObservation::getGid) @@ -422,7 +313,7 @@ private Map> initializeExistingGermp .collect(Collectors.toList()); try { - existingGermplasms.addAll(getGermplasmByAccessionNumber(uniqueGermplasmGIDs, program.getId())); + existingGermplasms = new ArrayList<>(getGermplasmByAccessionNumber(uniqueGermplasmGIDs, program.getId())); } catch (ApiException e) { log.error("Error fetching germplasm: " + Utilities.generateApiExceptionLogMessage(e), e); throw new InternalServerException(e.toString(), e); @@ -462,63 +353,5 @@ private ArrayList getGermplasmByAccessionNumber( return resultGermplasm; } - /** - * Fetches existing observations based on the given referenced traits, studyByNameNoScope map, and program. - * - * @param referencedTraits The list of referenced traits. - * @param studyByNameNoScope The map of studies by name without scope. - * @param program The program. - * @return A map of existing observations with their unique keys. - */ - private Map fetchExistingObservations(List referencedTraits, - Map> studyByNameNoScope, - Program program) { - Set ouDbIds = new HashSet<>(); - Set variableDbIds = new HashSet<>(); - Map variableNameByDbId = new HashMap<>(); - Map ouNameByDbId = new HashMap<>(); - Map studyNameByDbId = studyByNameNoScope.values() - .stream() - .filter(pio -> StringUtils.isNotBlank(pio.getBrAPIObject().getStudyDbId())) - .map(PendingImportObject::getBrAPIObject) - .collect(Collectors.toMap(BrAPIStudy::getStudyDbId, brAPIStudy -> Utilities.removeProgramKeyAndUnknownAdditionalData(brAPIStudy.getStudyName(), program.getKey()))); - - studyNameByDbId.keySet().forEach(studyDbId -> { - try { - brAPIObservationUnitDAO.getObservationUnitsForStudyDbId(studyDbId, program).forEach(ou -> { - if(StringUtils.isNotBlank(ou.getObservationUnitDbId())) { - ouDbIds.add(ou.getObservationUnitDbId()); - } - ouNameByDbId.put(ou.getObservationUnitDbId(), Utilities.removeProgramKeyAndUnknownAdditionalData(ou.getObservationUnitName(), program.getKey())); - }); - } catch (ApiException e) { - throw new RuntimeException(e); - } - }); - - for (Trait referencedTrait : referencedTraits) { - variableDbIds.add(referencedTrait.getObservationVariableDbId()); - variableNameByDbId.put(referencedTrait.getObservationVariableDbId(), referencedTrait.getObservationVariableName()); - } - - List existingObservations = new ArrayList<>(); - try { - existingObservations = brAPIObservationDAO.getObservationsByObservationUnitsAndVariables(ouDbIds, variableDbIds, program); - } catch (ApiException e) { - throw new RuntimeException(e); - } - - return existingObservations.stream() - .map(obs -> { - String studyName = studyNameByDbId.get(obs.getStudyDbId()); - String variableName = variableNameByDbId.get(obs.getObservationVariableDbId()); - String ouName = ouNameByDbId.get(obs.getObservationUnitDbId()); - - String key = ExperimentUtilities.getObservationHash(ExperimentUtilities.createObservationUnitKey(studyName, ouName), variableName, studyName); - - return Map.entry(key, obs); - }) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - } } \ No newline at end of file diff --git a/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/create/workflow/steps/PopulateNewPendingImportObjectsStep.java b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/create/workflow/steps/PopulateNewPendingImportObjectsStep.java index ab4f41505..eb79d2dc3 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/create/workflow/steps/PopulateNewPendingImportObjectsStep.java +++ b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/create/workflow/steps/PopulateNewPendingImportObjectsStep.java @@ -517,7 +517,7 @@ private PendingImportObject fetchOrCreateObsUnitPIO(Import String key = ExperimentUtilities.createObservationUnitKey(importRow); // NOTE: removed other workflow - if (observationUnitByNameNoScope.containsKey(key)) { + if (observationUnitByNameNoScope!=null && observationUnitByNameNoScope.containsKey(key)) { pio = observationUnitByNameNoScope.get(key); } else { String germplasmName = ""; @@ -552,6 +552,9 @@ private PendingImportObject fetchOrCreateObsUnitPIO(Import } else { pio = new PendingImportObject<>(ImportObjectState.NEW, newObservationUnit, id); } + if(observationUnitByNameNoScope==null){ + observationUnitByNameNoScope = new HashMap<>(); + } observationUnitByNameNoScope.put(key, pio); } return pio; diff --git a/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/services/ExperimentTrialService.java b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/services/ExperimentTrialService.java index b94fb6789..fc226370a 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/services/ExperimentTrialService.java +++ b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/services/ExperimentTrialService.java @@ -170,12 +170,10 @@ private void processAndCacheTrial( * * @throws InternalServerException */ - public Map> initializeTrialByNameNoScope(Program program, Map> observationUnitByNameNoScope, + public Map> initializeTrialByNameNoScope(Program program, List experimentImportRows) { Map> trialByName = new HashMap<>(); - initializeTrialsForExistingObservationUnits(program, observationUnitByNameNoScope, trialByName); - List uniqueTrialNames = experimentImportRows.stream() .map(ExperimentObservation::getExpTitle) .distinct()