Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ae4cdc4
[BI-2109] prepared BrAPITrialService for dataset work
mlm483 May 22, 2024
7669e0e
[BI-2109] added controller method and service method stub
mlm483 May 23, 2024
7d8fc93
[BI-2109] incorporated BI-1464 work, used dataset array on experiment
mlm483 May 29, 2024
37738f1
[BI-2109] - fixed enum serialization issue
mlm483 May 31, 2024
9fb3555
[BI-2109] - fully implemented createSubEntityDataset
mlm483 Jun 4, 2024
0f26eac
[BI-2109] - fixed DatasetLevel serialization in response
mlm483 Jun 5, 2024
a4786d7
[BI-2109] - fixed sub observation unit name
mlm483 Jun 10, 2024
086bd96
[BI-2109] - completed sub observation unit position
mlm483 Jun 10, 2024
c0214a9
[BI-2109] - indexed from 1
mlm483 Jun 10, 2024
f1a3d20
[BI-2109] - added RTK and Treament Factors
mlm483 Jun 10, 2024
11dcf7d
[BI-2109] - null handling
mlm483 Jun 10, 2024
27db242
[BI-2109] - added id to Dataset
mlm483 Jun 11, 2024
472d989
[BI-2109] - merged develop into feature/BI-2109
mlm483 Jun 11, 2024
23efe19
[BI-2109] - removed unused method
mlm483 Jun 12, 2024
2467cb0
[BI-2109] - cleaned up
mlm483 Jun 12, 2024
2f02edb
[BI-2109] - improved comments
mlm483 Jun 12, 2024
7090b60
[BI-2109] - handled null case
mlm483 Jun 12, 2024
4226ef2
[BI-2109] - cleaned up ExperimentProcessor.java changes
mlm483 Jun 12, 2024
cbaef19
[BI-2109] - cleaned up
mlm483 Jun 12, 2024
24fe163
[BI-2109] - fixed several tests
mlm483 Jun 12, 2024
5dd733c
[BI-2109] - fixed bug
mlm483 Jun 24, 2024
0d84705
[BI-2109] - fixed failing tests
mlm483 Jun 24, 2024
abf014d
[BI-2109] - implemented download by dataset
mlm483 Jun 26, 2024
913cc14
[BI-2109] - commented test
mlm483 Jun 27, 2024
2e0825d
[BI-2109] - fixed failing test
mlm483 Jun 27, 2024
8730d74
[BI-2109] - added sub-entity download test
mlm483 Jul 1, 2024
c64b129
[BI-2109] - cleaned up comment
mlm483 Jul 3, 2024
dd82dd7
[BI-2109] - added workaround until BI-2219 is implemented
mlm483 Jul 8, 2024
a82118f
[BI-2109] - added 404 response
mlm483 Jul 9, 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
@@ -0,0 +1,38 @@
/*
* 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.api.model.v1.request;

import io.micronaut.core.annotation.Introspected;
import lombok.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Getter
@Setter
@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Introspected
public class SubEntityDatasetRequest {
@NotBlank
private String name;
@NotNull
private int repeatedMeasures;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,25 @@
import io.micronaut.security.annotation.Secured;
import io.micronaut.security.rules.SecurityRule;
import lombok.extern.slf4j.Slf4j;
import org.brapi.client.v2.model.exceptions.ApiException;
import org.breedinginsight.api.auth.ProgramSecured;
import org.breedinginsight.api.auth.ProgramSecuredRoleGroup;
import org.breedinginsight.api.model.v1.request.SubEntityDatasetRequest;
import org.breedinginsight.api.model.v1.response.Response;
import org.breedinginsight.brapi.v2.model.request.query.ExperimentExportQuery;
import org.breedinginsight.brapi.v2.services.BrAPITrialService;
import org.breedinginsight.model.Dataset;
import org.breedinginsight.model.DatasetMetadata;
import org.breedinginsight.model.DownloadFile;
import org.breedinginsight.model.Program;
import org.breedinginsight.services.ProgramService;
import org.breedinginsight.services.exceptions.DoesNotExistException;
import org.breedinginsight.services.exceptions.UnprocessableEntityException;
import org.breedinginsight.utilities.response.mappers.ExperimentQueryMapper;

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

Expand Down Expand Up @@ -89,4 +94,57 @@ public HttpResponse<Response<Dataset>> getDatasetData(
}
}

/**
* Creates a sub-entity dataset for a given program and experiment with the specified name and number of repeated measures.
* @param programId The UUID of the program.
* @param experimentId The UUID of the experiment.
* @param datasetRequest The POST body, contains the dataset name and number of repeated measures to create.
* @return An HttpResponse with a Response object containing the newly created Dataset.
*/
@Post("/${micronaut.bi.api.version}/programs/{programId}/experiments/{experimentId}/dataset")
@ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL})
@Produces(MediaType.APPLICATION_JSON)
public HttpResponse<Response<Dataset>> createSubEntityDataset(
@PathVariable("programId") UUID programId,
@PathVariable("experimentId") UUID experimentId,
@Body @Valid SubEntityDatasetRequest datasetRequest) {
try {
Optional<Program> programOptional = programService.getById(programId);
if (programOptional.isEmpty()) {
return HttpResponse.status(HttpStatus.NOT_FOUND, "Program does not exist");
}

Response<Dataset> response = new Response(experimentService.createSubEntityDataset(programOptional.get(), experimentId, datasetRequest));
return HttpResponse.ok(response);
} catch (Exception e){
log.info(e.getMessage());
return HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY, e.getMessage());
}
}

/**
* Retrieves the datasets for a given program and experiment.
*
* @param programId The UUID of the program.
* @param experimentId The UUID of the experiment.
* @return An HttpResponse with a Response object containing a list of DatasetMetadata.
* @throws DoesNotExistException if the program does not exist.
* @throws ApiException if an error occurs while retrieving the datasets.
*/
@Get("/${micronaut.bi.api.version}/programs/{programId}/experiments/{experimentId}/datasets")
@ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL})
@Produces(MediaType.APPLICATION_JSON)
public HttpResponse<Response<List<DatasetMetadata>>> getDatasets(
@PathVariable("programId") UUID programId,
@PathVariable("experimentId") UUID experimentId) throws DoesNotExistException, ApiException {

Optional<Program> programOptional = programService.getById(programId);
if (programOptional.isEmpty()) {
return HttpResponse.status(HttpStatus.NOT_FOUND, "Program does not exist");
}

Response<List<DatasetMetadata>> response = new Response(experimentService.getDatasetsMetadata(programOptional.get(), experimentId));
return HttpResponse.ok(response);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ public final class BrAPIAdditionalInfoFields {
public static final String EXPERIMENT_NUMBER = "experimentNumber";
public static final String ENVIRONMENT_NUMBER = "environmentNumber";
public static final String STUDY_NAME = "studyName";
@Deprecated
public static final String OBSERVATION_DATASET_ID = "observationDatasetId";
public static final String DATASETS = "datasets";
public static final String FEMALE_PARENT_UNKNOWN = "femaleParentUnknown";
public static final String MALE_PARENT_UNKNOWN = "maleParentUnknown";
public static final String TREATMENTS = "treatments";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,24 @@ public List<BrAPIObservation> getObservationsByObservationUnitsAndVariables(Coll
.collect(Collectors.toList());
}

public List<BrAPIObservation> getObservationsByObservationUnits(Collection<String> ouDbIds, Program program) throws ApiException {
if(ouDbIds.isEmpty()) {
return Collections.emptyList();
}
return getProgramObservations(program.getId()).values().stream()
.filter(o -> ouDbIds.contains(o.getObservationUnitDbId()))
.collect(Collectors.toList());
}

public List<BrAPIObservation> getObservationsByObservationUnitsAndStudies(Collection<String> ouDbIds, Collection<String> studyDbIds, Program program) throws ApiException {
if(ouDbIds.isEmpty()) {
return Collections.emptyList();
}
return getProgramObservations(program.getId()).values().stream()
.filter(o -> ouDbIds.contains(o.getObservationUnitDbId()) && studyDbIds.contains(o.getStudyDbId()))
.collect(Collectors.toList());
}

@NotNull
private ApiResponse<Pair<Optional<BrAPIObservationListResponse>, Optional<BrAPIAcceptedSearchResponse>>> searchObservationsSearchResultsDbIdGet(UUID programId, String searchResultsDbId, Integer page, Integer pageSize) throws ApiException {
ObservationsApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(programId), ObservationsApi.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ public List<BrAPIObservationUnit> getObservationUnitByName(List<String> observat
}

/**
* Create observation units, mutates brAPIObservationUnitList
* Create observation units with import progress.
* Mutates brAPIObservationUnitList.
*/
public List<BrAPIObservationUnit> createBrAPIObservationUnits(List<BrAPIObservationUnit> brAPIObservationUnitList, UUID programId, ImportUpload upload) throws ApiException, DoesNotExistException {
Program program = programService.getById(programId).orElseThrow(() -> new DoesNotExistException("Program id does not exist"));
Expand All @@ -190,6 +191,28 @@ public List<BrAPIObservationUnit> createBrAPIObservationUnits(List<BrAPIObservat
}
}

/**
* Create observation units without import progress.
* Mutates brAPIObservationUnitList.
*/
public List<BrAPIObservationUnit> createBrAPIObservationUnits(List<BrAPIObservationUnit> brAPIObservationUnitList, UUID programId) throws ApiException, DoesNotExistException {
Program program = programService.getById(programId).orElseThrow(() -> new DoesNotExistException("Program id does not exist"));
ObservationUnitsApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(programId), ObservationUnitsApi.class);
try {
if (!brAPIObservationUnitList.isEmpty()) {
Callable<Map<String, BrAPIObservationUnit>> postFunction = () -> {
preprocessObservationUnits(brAPIObservationUnitList);
List<BrAPIObservationUnit> ous = brAPIDAOUtil.post(brAPIObservationUnitList, api::observationunitsPost);
return processObservationUnitsForCache(ous, program, false);
};
return programObservationUnitCache.post(programId, postFunction);
}
return new ArrayList<>();
} catch (Exception e) {
throw new InternalServerException("Unknown error has occurred: " + e.getMessage(), e);
}
}

public List<BrAPIObservationUnit> getObservationUnitsById(Collection<String> observationUnitExternalIds, Program program) throws ApiException {
if(observationUnitExternalIds.isEmpty()) {
return Collections.emptyList();
Expand Down Expand Up @@ -231,6 +254,21 @@ public List<BrAPIObservationUnit> getObservationUnitsForDataset(@NotNull String
.collect(Collectors.toList());
}

public List<BrAPIObservationUnit> getObservationUnitsForDatasetAndEnvs(@NotNull String datasetId, Collection<String> envIds, @NotNull Program program) throws ApiException {
String datasetReferenceSource = Utilities.generateReferenceSource(referenceSource, ExternalReferenceSource.DATASET);
String studyReferenceSource = Utilities.generateReferenceSource(referenceSource, ExternalReferenceSource.STUDIES);
return getProgramObservationUnits(program.getId()).values().stream()
.filter(ou -> {
Optional<BrAPIExternalReference> datasetExRef = Utilities.getExternalReference(ou.getExternalReferences(), datasetReferenceSource);
Optional<BrAPIExternalReference> studyExRef = Utilities.getExternalReference(ou.getExternalReferences(), studyReferenceSource);
return Boolean.logicalAnd(
datasetExRef.map(x -> x.getReferenceId().equals(datasetId)).orElse(false),
studyExRef.map(x -> envIds.contains(x.getReferenceId())).orElse(false)
);
})
.collect(Collectors.toList());
}

// Note: does not use cache, impractical to implement all search parameters client-side.
public List<BrAPIObservationUnit> getObservationUnits(Program program,
Optional<String> observationUnitId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
@ToString
public class ExperimentExportQuery {
private FileType fileExtension;
private String dataset;
private String datasetId;
private String environments;
@NotNull
private boolean includeTimestamps;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.breedinginsight.model.*;
import org.breedinginsight.services.ProgramService;
import org.breedinginsight.services.exceptions.DoesNotExistException;
import org.breedinginsight.utilities.DatasetUtil;
import org.breedinginsight.utilities.Utilities;
import org.jetbrains.annotations.NotNull;

Expand All @@ -55,6 +56,8 @@ public BrAPIObservationVariableService(
this.referenceSource = referenceSource;
}

// TODO: support sub-entity datasets.
// This gets the observation variables for the top-level dataset in an experiment.
public List<Trait> getBrAPIObservationVariablesForExperiment(
UUID programId,
Optional<String> experimentId,
Expand All @@ -78,12 +81,10 @@ public List<Trait> getBrAPIObservationVariablesForExperiment(
}

BrAPITrial experiment = trialService.getExperiment(program.get(), expId);
if(experiment
.getAdditionalInfo().getAsJsonObject()
.has(BrAPIAdditionalInfoFields.OBSERVATION_DATASET_ID)) {
String obsDatasetId = experiment
.getAdditionalInfo().getAsJsonObject()
.get(BrAPIAdditionalInfoFields.OBSERVATION_DATASET_ID).getAsString();
if(!experiment.getAdditionalInfo().getAsJsonArray(BrAPIAdditionalInfoFields.DATASETS).isEmpty()) {
String obsDatasetId = DatasetUtil
.getTopLevelDatasetFromJson(experiment.getAdditionalInfo().getAsJsonArray(BrAPIAdditionalInfoFields.DATASETS))
.getId().toString();
return trialService.getDatasetObsVars(obsDatasetId, program.get());
}

Expand Down
Loading