diff --git a/src/main/java/org/breedinginsight/brapi/v2/BrAPIV2Controller.java b/src/main/java/org/breedinginsight/brapi/v2/BrAPIV2Controller.java index 7b5f07f74..0dcaa029b 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/BrAPIV2Controller.java +++ b/src/main/java/org/breedinginsight/brapi/v2/BrAPIV2Controller.java @@ -27,29 +27,19 @@ import io.micronaut.security.rules.SecurityRule; import lombok.extern.slf4j.Slf4j; import okhttp3.*; -import org.brapi.client.v2.model.exceptions.ApiException; -import org.brapi.v2.model.core.BrAPIListSummary; import org.brapi.v2.model.core.BrAPIServerInfo; import org.brapi.v2.model.core.response.BrAPIServerInfoResponse; import org.breedinginsight.api.auth.AuthenticatedUser; import org.breedinginsight.api.auth.ProgramSecured; import org.breedinginsight.api.auth.ProgramSecuredRoleGroup; import org.breedinginsight.api.auth.SecurityService; -import org.breedinginsight.api.model.v1.request.query.SearchRequest; -import org.breedinginsight.api.model.v1.validators.QueryValid; import org.breedinginsight.brapi.v1.controller.BrapiVersion; -import org.breedinginsight.brapi.v2.model.request.query.ListQuery; -import org.breedinginsight.utilities.response.mappers.ListQueryMapper; -import org.breedinginsight.brapi.v2.services.BrAPIGermplasmService; import org.breedinginsight.model.ProgramBrAPIEndpoints; import org.breedinginsight.services.ProgramService; import org.breedinginsight.services.exceptions.DoesNotExistException; -import org.breedinginsight.utilities.response.ResponseUtils; import javax.inject.Inject; -import javax.validation.Valid; import java.io.IOException; -import java.util.List; import java.util.UUID; import java.util.stream.Collectors; @@ -60,16 +50,11 @@ public class BrAPIV2Controller { private final SecurityService securityService; private final ProgramService programService; - private final BrAPIGermplasmService germplasmService; - private ListQueryMapper listQueryMapper; @Inject - public BrAPIV2Controller(SecurityService securityService, ProgramService programService, BrAPIGermplasmService germplasmService, - ListQueryMapper listQueryMapper) { + public BrAPIV2Controller(SecurityService securityService, ProgramService programService) { this.securityService = securityService; this.programService = programService; - this.germplasmService = germplasmService; - this.listQueryMapper = listQueryMapper; } @@ -86,43 +71,6 @@ public BrAPIServerInfoResponse serverinfo() { return new BrAPIServerInfoResponse().result(serverInfo); } - //@Get(BrapiVersion.BRAPI_V2 + "/lists") - @Get("/${micronaut.bi.api.version}/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/lists{?queryParams*}") - @Produces(MediaType.APPLICATION_JSON) - @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) - public HttpResponse getLists(@PathVariable("programId") UUID programId, HttpRequest request, - @QueryValue @QueryValid(using = ListQueryMapper.class) @Valid ListQuery queryParams - ) throws DoesNotExistException, ApiException { - try { - List brapiLists; - - // If the date display format was sent as a query param, then update the query mapper. - String dateFormatParam = queryParams.getDateDisplayFormat(); - if (dateFormatParam != null) { - listQueryMapper.setDateDisplayFormat(dateFormatParam); - } - - if (queryParams.getListType() == null) { - // TODO: in future return all list types but for now just return germplasm - brapiLists = germplasmService.getGermplasmListsByProgramId(programId, request); - } else { - // TODO: return appropriate lists by type, only germplasm currently - switch (queryParams.getListType()) { - case "germplasm": - default: - brapiLists = germplasmService.getGermplasmListsByProgramId(programId, request); - } - } - - SearchRequest searchRequest = queryParams.constructSearchRequest(); - return ResponseUtils.getBrapiQueryResponse(brapiLists, listQueryMapper, queryParams, searchRequest); - - } catch (IllegalArgumentException e) { - log.info(e.getMessage(), e); - return HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY, "Error parsing requested date format"); - } - } - @Get("/${micronaut.bi.api.version}/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/{+path}") @Produces(MediaType.APPLICATION_JSON) @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) diff --git a/src/main/java/org/breedinginsight/brapi/v2/ExperimentController.java b/src/main/java/org/breedinginsight/brapi/v2/ExperimentController.java index 4e4a67f18..6e7ebedcd 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/ExperimentController.java +++ b/src/main/java/org/breedinginsight/brapi/v2/ExperimentController.java @@ -21,6 +21,7 @@ import org.breedinginsight.brapi.v2.model.request.query.ExperimentExportQuery; import org.breedinginsight.brapi.v2.model.request.query.ExperimentQuery; import org.breedinginsight.brapi.v2.services.BrAPITrialService; +import org.breedinginsight.model.Dataset; import org.breedinginsight.model.DownloadFile; import org.breedinginsight.model.Program; import org.breedinginsight.services.ProgramService; @@ -108,9 +109,26 @@ public HttpResponse datasetExport( HttpResponse response = HttpResponse.status(HttpStatus.INTERNAL_SERVER_ERROR, downloadErrorMessage).contentType(MediaType.TEXT_PLAIN).body(downloadErrorMessage); return response; } - - } + @Get("/${micronaut.bi.api.version}/programs/{programId}/experiments/{experimentId}/dataset/{datasetId}{?stats}") + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + @Produces(MediaType.APPLICATION_JSON) + public HttpResponse> getDatasetData( + @PathVariable("programId") UUID programId, + @PathVariable("experimentId") UUID experimentId, + @PathVariable("datasetId") UUID datasetId, + @QueryValue(defaultValue = "false") Boolean stats) { + String downloadErrorMessage = "An error occurred while fetching the dataset. Contact the development team at bidevteam@cornell.edu."; + try { + Program program = programService.getById(programId).orElseThrow(() -> new DoesNotExistException("Program does not exist")); + Response response = new Response(experimentService.getDatasetData(program, experimentId, datasetId, stats)); + return HttpResponse.ok(response); + } catch (Exception e) { + log.info(e.getMessage(), e); + HttpResponse response = HttpResponse.status(HttpStatus.INTERNAL_SERVER_ERROR, downloadErrorMessage).contentType(MediaType.TEXT_PLAIN).body(downloadErrorMessage); + return response; + } + } } diff --git a/src/main/java/org/breedinginsight/brapi/v2/ListController.java b/src/main/java/org/breedinginsight/brapi/v2/ListController.java new file mode 100644 index 000000000..59caa8a47 --- /dev/null +++ b/src/main/java/org/breedinginsight/brapi/v2/ListController.java @@ -0,0 +1,111 @@ +/* + * 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.brapi.v2; + +import io.micronaut.http.HttpResponse; +import io.micronaut.http.HttpStatus; +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.*; +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.brapi.v2.model.core.BrAPIListSummary; +import org.brapi.v2.model.core.BrAPIListTypes; +import org.breedinginsight.api.auth.ProgramSecured; +import org.breedinginsight.api.auth.ProgramSecuredRoleGroup; +import org.breedinginsight.api.model.v1.request.query.SearchRequest; +import org.breedinginsight.api.model.v1.response.DataResponse; +import org.breedinginsight.api.model.v1.response.Response; +import org.breedinginsight.api.model.v1.validators.QueryValid; +import org.breedinginsight.brapi.v1.controller.BrapiVersion; +import org.breedinginsight.brapi.v2.model.request.query.ListQuery; +import org.breedinginsight.brapi.v2.services.BrAPIListService; +import org.breedinginsight.model.Program; +import org.breedinginsight.services.ProgramService; +import org.breedinginsight.services.exceptions.DoesNotExistException; +import org.breedinginsight.utilities.response.ResponseUtils; +import org.breedinginsight.utilities.response.mappers.ListQueryMapper; + +import javax.inject.Inject; +import javax.validation.Valid; +import java.util.List; +import java.util.UUID; + +@Slf4j +@Controller +@Secured(SecurityRule.IS_AUTHENTICATED) +public class ListController { + + private final ProgramService programService; + private final BrAPIListService listService; + private final ListQueryMapper listQueryMapper; + + @Inject + public ListController(ProgramService programService, BrAPIListService listService, + ListQueryMapper listQueryMapper) { + this.programService = programService; + this.listService = listService; + this.listQueryMapper = listQueryMapper; + } + + //@Get(BrapiVersion.BRAPI_V2 + "/lists") + @Get("/${micronaut.bi.api.version}/programs/{programId}" + BrapiVersion.BRAPI_V2 + "/lists{?queryParams*}") + @Produces(MediaType.APPLICATION_JSON) + @ProgramSecured(roleGroups = {ProgramSecuredRoleGroup.ALL}) + public HttpResponse>> getLists( + @PathVariable("programId") UUID programId, + @QueryValue @QueryValid(using = ListQueryMapper.class) @Valid ListQuery queryParams + ) throws DoesNotExistException, ApiException { + try { + Program program = programService + .getById(programId) + .orElseThrow(() -> new DoesNotExistException("Program does not exist")); + + // get germplasm lists by default + BrAPIListTypes type = BrAPIListTypes.fromValue(queryParams.getListType()); + if (type == null) { + type = BrAPIListTypes.GERMPLASM; + } + String source = null; + String id = null; + if (queryParams.getExternalReferenceSource() != null && !queryParams.getExternalReferenceSource().isEmpty()) { + source = queryParams.getExternalReferenceSource(); + } + if (queryParams.getExternalReferenceId() != null && !queryParams.getExternalReferenceId().isEmpty()) { + id = queryParams.getExternalReferenceId(); + } + + // If the date display format was sent as a query param, then update the query mapper. + String dateFormatParam = queryParams.getDateDisplayFormat(); + if (dateFormatParam != null) { + listQueryMapper.setDateDisplayFormat(dateFormatParam); + } + List brapiLists = listService.getListSummariesByTypeAndXref(type, source, id, program); + SearchRequest searchRequest = queryParams.constructSearchRequest(); + + return ResponseUtils.getBrapiQueryResponse(brapiLists, listQueryMapper, queryParams, searchRequest); + + } catch (IllegalArgumentException e) { + log.info(e.getMessage(), e); + return HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY, "Error parsing requested date format"); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/org/breedinginsight/brapi/v2/model/request/query/ListQuery.java b/src/main/java/org/breedinginsight/brapi/v2/model/request/query/ListQuery.java index 8e379f788..c1b9c6f33 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/model/request/query/ListQuery.java +++ b/src/main/java/org/breedinginsight/brapi/v2/model/request/query/ListQuery.java @@ -5,6 +5,7 @@ import org.breedinginsight.api.model.v1.request.query.FilterRequest; import org.breedinginsight.api.model.v1.request.query.SearchRequest; import org.breedinginsight.brapi.v1.model.request.query.BrapiQuery; +import org.breedinginsight.brapps.importer.services.ExternalReferenceSource; import org.jooq.tools.StringUtils; import java.util.ArrayList; @@ -17,6 +18,8 @@ public class ListQuery extends BrapiQuery { private String name; private String description; private String size; + private String externalReferenceSource; + private String externalReferenceId; private String dateCreated; private String ownerName; // This is a meta-parameter, it describes the display format of any date fields. @@ -24,7 +27,7 @@ public class ListQuery extends BrapiQuery { public SearchRequest constructSearchRequest() { List filters = new ArrayList<>(); - if (!StringUtils.isBlank(getListType())) { + if (getListType() != null) { filters.add(constructFilterRequest("type", getListType())); } if (!StringUtils.isBlank(getName())) { @@ -36,6 +39,12 @@ public SearchRequest constructSearchRequest() { if (!StringUtils.isBlank(getSize())) { filters.add(constructFilterRequest("size", getSize())); } + if (getExternalReferenceSource() != null) { + filters.add(constructFilterRequest("externalReferenceSource", getExternalReferenceSource())); + } + if (!StringUtils.isBlank(getExternalReferenceId())) { + filters.add(constructFilterRequest("externalReferenceId", getExternalReferenceId())); + } if (!StringUtils.isBlank(getDateCreated())) { filters.add(constructFilterRequest("dateCreated", getDateCreated())); } diff --git a/src/main/java/org/breedinginsight/brapi/v2/services/BrAPIListService.java b/src/main/java/org/breedinginsight/brapi/v2/services/BrAPIListService.java new file mode 100644 index 000000000..7d69e831a --- /dev/null +++ b/src/main/java/org/breedinginsight/brapi/v2/services/BrAPIListService.java @@ -0,0 +1,92 @@ +package org.breedinginsight.brapi.v2.services; + +import io.micronaut.context.annotation.Property; +import lombok.extern.slf4j.Slf4j; +import org.brapi.client.v2.model.exceptions.ApiException; +import org.brapi.v2.model.BrAPIExternalReference; +import org.brapi.v2.model.core.BrAPIListSummary; +import org.brapi.v2.model.core.BrAPIListTypes; +import org.brapi.v2.model.core.request.BrAPIListSearchRequest; +import org.brapi.v2.model.core.response.BrAPIListsSingleResponse; +import org.breedinginsight.brapi.v2.dao.BrAPIGermplasmDAO; +import org.breedinginsight.brapps.importer.daos.*; +import org.breedinginsight.brapps.importer.services.ExternalReferenceSource; +import org.breedinginsight.model.Program; +import org.breedinginsight.services.exceptions.DoesNotExistException; +import org.breedinginsight.utilities.Utilities; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +@Slf4j +@Singleton +public class BrAPIListService { + private final String referenceSource; + private final BrAPIListDAO listDAO; + private final BrAPIGermplasmDAO germplasmDAO; + + @Inject + public BrAPIListService(@Property(name = "brapi.server.reference-source") String referenceSource, + BrAPIListDAO listDAO, + BrAPIGermplasmDAO germplasmDAO) { + + this.referenceSource = referenceSource; + this.listDAO = listDAO; + this.germplasmDAO = germplasmDAO; + } + + public List getListSummariesByTypeAndXref( + BrAPIListTypes type, + String xrefSource, + String xrefId, + Program program) throws ApiException, DoesNotExistException, ClassNotFoundException { + BrAPIListSearchRequest searchRequest = new BrAPIListSearchRequest(); + if (type != null) { + searchRequest.listType(type); + } + if (xrefSource != null && !xrefSource.isEmpty()) { + searchRequest.externalReferenceSources(List.of(xrefSource)); + } + if (xrefId != null && !xrefId.isEmpty()) { + searchRequest.externalReferenceIDs(List.of(xrefId)); + } + List lists = listDAO.getListBySearch(searchRequest, program.getId()); + if (lists == null) { + throw new DoesNotExistException("list not returned from BrAPI service"); + } + + List programLists = lists.stream().filter(list -> { + Optional programXrefOptional = Utilities.getExternalReference(list.getExternalReferences(),Utilities.generateReferenceSource(referenceSource, ExternalReferenceSource.PROGRAMS)); + return programXrefOptional.isPresent() && programXrefOptional.get().getReferenceID().equals(program.getId().toString()); + }).collect(Collectors.toList()); + for (BrAPIListSummary list: programLists) { + + // remove the program key from the list name + list.setListName(Utilities.removeProgramKeyAndUnknownAdditionalData(list.getListName(), program.getKey())); + + // set the owner of the list items as the list owner + BrAPIListsSingleResponse listDetails = listDAO.getListById(list.getListDbId(), program.getId()); + List listItemNames = listDetails.getResult().getData(); + switch (type) { + case OBSERVATIONVARIABLES: + break; + case GERMPLASM: + default: + String createdBy = germplasmDAO.getGermplasmByRawName(listItemNames, program.getId()).get(0) + .getAdditionalInfo() + .getAsJsonObject("createdBy") + .get("userName") + .getAsString(); + list.setListOwnerName(createdBy); + } + + } + + return programLists; + } +} diff --git a/src/main/java/org/breedinginsight/brapi/v2/services/BrAPITrialService.java b/src/main/java/org/breedinginsight/brapi/v2/services/BrAPITrialService.java index c66671355..9198e160d 100644 --- a/src/main/java/org/breedinginsight/brapi/v2/services/BrAPITrialService.java +++ b/src/main/java/org/breedinginsight/brapi/v2/services/BrAPITrialService.java @@ -22,6 +22,7 @@ import org.breedinginsight.model.Column; import org.breedinginsight.model.DownloadFile; import org.breedinginsight.model.Program; +import org.breedinginsight.model.*; import org.breedinginsight.services.exceptions.DoesNotExistException; import org.breedinginsight.services.parsers.experiment.ExperimentFileColumns; import org.breedinginsight.services.writers.CSVWriter; @@ -198,6 +199,33 @@ public DownloadFile exportObservations( return new DownloadFile(fileName, downloadFile); } + public Dataset getDatasetData(Program program, UUID experimentId, UUID datsetId, Boolean stats) throws ApiException, DoesNotExistException { + BrAPITrial experiment = this.getExperiment(program, experimentId); + + // TODO: Once BI-1831 is complete and OUs in a dataset can be identified using the datasetId stored as a xref + // the expOUs needs to be replaced with datasetOUs, as was done with datasetObsVars + List expOUs = ouDAO.getObservationUnitsForTrialDbId(program.getId(), experiment.getTrialDbId()); + List datasetObsVars = getDatasetObsVars(datsetId.toString(), program); + List ouDbIds = expOUs.stream().map(BrAPIObservationUnit::getObservationUnitDbId).collect(Collectors.toList()); + List obsVarDbIds = datasetObsVars.stream().map(BrAPIObservationVariable::getObservationVariableDbId).collect(Collectors.toList()); + List data = observationDAO.getObservationsByObservationUnitsAndVariables(ouDbIds, obsVarDbIds, program); + Dataset dataset = new Dataset(experimentId.toString(), data, expOUs, datasetObsVars); + if (stats) { + Integer ouCount = expOUs.size(); + Integer obsVarCount = datasetObsVars.size(); + Integer obsCount = ouCount * obsVarCount; + Integer obsDataCount = data.size(); + Integer emptyDataCount = obsCount - obsDataCount; + dataset = dataset.setStat(Dataset.DatasetStat.OBSERVATION_UNITS, ouCount) + .setStat(Dataset.DatasetStat.PHENOTYPES, obsVarCount) + .setStat(Dataset.DatasetStat.OBSERVATIONS, obsCount) + .setStat(Dataset.DatasetStat.OBSERVATIONS_WITH_DATA, obsDataCount) + .setStat(Dataset.DatasetStat.OBSERVATIONS_WITHOUT_DATA, emptyDataCount); + } + + return dataset; + } + private void addBrAPIObsToRecords( List dataset, BrAPITrial experiment, diff --git a/src/main/java/org/breedinginsight/brapps/importer/daos/BrAPIListDAO.java b/src/main/java/org/breedinginsight/brapps/importer/daos/BrAPIListDAO.java index a919fcf8d..cb24fd745 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/daos/BrAPIListDAO.java +++ b/src/main/java/org/breedinginsight/brapps/importer/daos/BrAPIListDAO.java @@ -64,6 +64,18 @@ public BrAPIListsSingleResponse getListById(String listId, UUID programId) throw return response.getBody(); } + public List getListBySearch(@NotNull BrAPIListSearchRequest searchRequest, UUID programId) throws ApiException { + ListsApi api = brAPIEndpointProvider.get(programDAO.getCoreClient(programId), ListsApi.class); + List programLists = brAPIDAOUtil.search(api::searchListsPost, api::searchListsSearchResultsDbIdGet, searchRequest); + if (searchRequest.getExternalReferenceSources() != null && searchRequest.getExternalReferenceIDs() != null) { + programLists = processListsForProgram(programLists, + UUID.fromString(searchRequest.getExternalReferenceIDs().get(0)), + searchRequest.getExternalReferenceSources().get(0)); + } + return programLists; + + } + public List getListByTypeAndExternalRef(@NotNull BrAPIListTypes listType, UUID programId, String externalReferenceSource, UUID externalReferenceId) throws ApiException { BrAPIListSearchRequest searchRequest = new BrAPIListSearchRequest() .externalReferenceIDs(List.of(externalReferenceId.toString())) diff --git a/src/main/java/org/breedinginsight/brapps/importer/services/ExternalReferenceSource.java b/src/main/java/org/breedinginsight/brapps/importer/services/ExternalReferenceSource.java index aa2fd1d75..9e95bfd41 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/services/ExternalReferenceSource.java +++ b/src/main/java/org/breedinginsight/brapps/importer/services/ExternalReferenceSource.java @@ -13,7 +13,7 @@ public enum ExternalReferenceSource { private String name; - ExternalReferenceSource(String name) { + private ExternalReferenceSource(String name) { this.name = name; } } diff --git a/src/main/java/org/breedinginsight/model/Dataset.java b/src/main/java/org/breedinginsight/model/Dataset.java new file mode 100644 index 000000000..bcc8b357a --- /dev/null +++ b/src/main/java/org/breedinginsight/model/Dataset.java @@ -0,0 +1,47 @@ +package org.breedinginsight.model; + +import com.google.gson.JsonObject; +import org.brapi.v2.model.pheno.BrAPIObservation; +import org.brapi.v2.model.pheno.BrAPIObservationUnit; +import org.brapi.v2.model.pheno.BrAPIObservationVariable; + +import java.util.List; + +public class Dataset { + public String experimentId; + public JsonObject additionalInfo; + public List data; + public List observationUnits; + public List observationVariables; + + public enum DatasetStat { + OBSERVATION_UNITS("observationUnits"), + PHENOTYPES("phenotypes"), + OBSERVATIONS("observations"), + OBSERVATIONS_WITH_DATA("observationsWithData"), + OBSERVATIONS_WITHOUT_DATA("observationsWithoutData"); + + private final String displayName; + DatasetStat(String value) { + this.displayName = value; + } + + } + + public Dataset( + String experimentId, + List data, + List observationUnits, + List observationVariables) { + this.experimentId = experimentId; + this.additionalInfo = new JsonObject(); + this.data = data; + this.observationUnits = observationUnits; + this.observationVariables = observationVariables; + } + + public Dataset setStat(DatasetStat stat, Integer count) { + this.additionalInfo.addProperty(stat.displayName, count); + return this; + } +} diff --git a/src/main/java/org/breedinginsight/utilities/response/mappers/ListQueryMapper.java b/src/main/java/org/breedinginsight/utilities/response/mappers/ListQueryMapper.java index a8155864d..05c5a6ba4 100644 --- a/src/main/java/org/breedinginsight/utilities/response/mappers/ListQueryMapper.java +++ b/src/main/java/org/breedinginsight/utilities/response/mappers/ListQueryMapper.java @@ -3,12 +3,17 @@ import lombok.Getter; import lombok.Setter; import org.brapi.v2.model.core.BrAPIListSummary; +import org.breedinginsight.brapps.importer.model.base.ExternalReference; +import org.breedinginsight.brapps.importer.services.ExternalReferenceSource; import javax.inject.Singleton; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.function.Function; +import java.util.stream.Collectors; @Getter @Singleton @@ -36,7 +41,21 @@ public ListQueryMapper() { return dateCreated; }), Map.entry("ownerName", BrAPIListSummary::getListOwnerName), - Map.entry("type", BrAPIListSummary::getListType) + Map.entry("type", BrAPIListSummary::getListType), + Map.entry("externalReferenceSource", (summary) -> { + return summary + .getExternalReferences() + .stream() + .map(xref -> xref.getReferenceSource()) + .collect(Collectors.toList()); + }), + Map.entry("externalReferenceId", (summary) -> { + return summary + .getExternalReferences() + .stream() + .map(xref -> xref.getReferenceID()) + .collect(Collectors.toList()); + }) ); }