Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
3640e5d
Add new filter/sort models
jloux-brapi May 7, 2026
fd64178
Preliminary generic sortBy implementation on searchRequests
jloux-brapi May 7, 2026
32664a2
Use @Formula to derive needed addInfo entity attrs, update SearchQuer…
jloux-brapi May 21, 2026
2d51285
Preliminary pass at allowed fields mapping
jloux-brapi May 21, 2026
f9440f0
Add parametrization logic for filter values, infrastructure for 400 e…
jloux-brapi May 22, 2026
90214e0
Use new SortBy class in all use cases.
jloux-brapi May 22, 2026
90e77dd
Make filter case insensitive
jloux-brapi May 29, 2026
3bf581a
Fix pom jackson depedency issues
jloux-brapi Jun 1, 2026
da60a1a
Migrate parent observation ids on ou_level to brapi dbIds
jloux-brapi Jul 21, 2026
c2afc76
Add some clarifying comments
jloux-brapi Jul 21, 2026
5809fa9
Merge branch 'develop' into feature/BI-2861
jloux-brapi Jul 21, 2026
47e1c27
Merge branch 'feature/BI-2861' into feature/BI-2995
jloux-brapi Jul 21, 2026
56c9821
Migrate sample bi ouIds to brapi ouIds
jloux-brapi Jul 22, 2026
e079626
Add back in distinct to general search build query
jloux-brapi Jul 24, 2026
647b44f
Implement data types for filtering
jloux-brapi Jul 27, 2026
b095c97
Add code for filtering on one to many relationship entity collections
jloux-brapi Aug 3, 2026
05fb082
Fix issue with sorting for GET study/trial endpoints
jloux-brapi Aug 4, 2026
b0bf8ba
Fix issues with using distinct in sorting
jloux-brapi Aug 6, 2026
22736ae
Add Pattern to end of filter params in SearchQueryBuilder
jloux-brapi Aug 7, 2026
2bd1d47
Create migration script, add programDbId to entity and model
jloux-brapi Aug 10, 2026
2bad4ff
Support for programId in GermplasmApi
jloux-brapi Aug 11, 2026
5a747b4
Use more restrictive exref query, add assertion to migration
jloux-brapi Aug 18, 2026
c17b97a
Add semicolon
jloux-brapi Aug 18, 2026
3867e85
Merge branch 'feature/BI-2995' into feature/BI-2996
jloux-brapi Aug 18, 2026
cc05724
Update comment
jloux-brapi Aug 19, 2026
7358397
Merge branch 'feature/BI-2995' into feature/BI-2996
jloux-brapi Aug 19, 2026
cc82ecd
Update migration script with stricter matching to OU, add assertion
jloux-brapi Aug 19, 2026
bd8e00a
Merge branch 'feature/BI-2996' into feature/BI-2903
jloux-brapi Aug 19, 2026
b6f2c9b
Merge branch 'develop' into feature/BI-2861
jloux-brapi Aug 20, 2026
6a928e3
Merge branch 'feature/BI-2861' into feature/BI-2995
jloux-brapi Aug 20, 2026
9f20402
Merge branch 'feature/BI-2995' into feature/BI-2996
jloux-brapi Aug 20, 2026
ad1c04a
Merge branch 'feature/BI-2996' into feature/BI-2903
jloux-brapi Aug 20, 2026
b308330
Undo removed changes from develop
jloux-brapi Aug 20, 2026
cb8c576
Merge branch 'feature/BI-2861' into feature/BI-2995
jloux-brapi Aug 20, 2026
05478ff
Merge branch 'feature/BI-2995' into feature/BI-2996
jloux-brapi Aug 20, 2026
7248c4d
Merge branch 'feature/BI-2996' into feature/BI-2903
jloux-brapi Aug 20, 2026
265da14
Ignore getMethod on sortFilter map that was breaking async use case
jloux-brapi Aug 24, 2026
f57dc76
Merge branch 'feature/BI-2861' into feature/BI-2995
jloux-brapi Aug 24, 2026
6c60dc0
Merge branch 'feature/BI-2995' into feature/BI-2996
jloux-brapi Aug 24, 2026
ef2bade
Merge branch 'feature/BI-2996' into feature/BI-2903
jloux-brapi Aug 24, 2026
ccc5e1d
Merge pull request #17 from Breeding-Insight/feature/BI-2861
jloux-brapi Aug 24, 2026
7de362b
Merge pull request #19 from Breeding-Insight/feature/BI-2995
jloux-brapi Aug 24, 2026
d2a62d2
Merge pull request #20 from Breeding-Insight/feature/BI-2996
jloux-brapi Aug 24, 2026
5a39677
Fix createEntities in batch error, address migration concerns
jloux-brapi Aug 26, 2026
5bdde47
Merge pull request #23 from Breeding-Insight/feature/BI-2903
jloux-brapi Aug 27, 2026
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
1 change: 1 addition & 0 deletions src/main/java/io/swagger/api/germ/GermplasmApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ ResponseEntity<GermplasmListResponse> germplasmGet(
@ApiParam(value = "progenyDbId") @Valid @RequestParam(value = "progenyDbId", required = false) String progenyDbId,
@ApiParam(value = "commonCropName") @Valid @RequestParam(value = "commonCropName", required = false) String commonCropName,
@ApiParam(value = "programDbId") @Valid @RequestParam(value = "programDbId", required = false) String programDbId,
@ApiParam(value = "programName") @Valid @RequestParam(value = "programName", required = false) String programName,
@ApiParam(value = "externalReferenceID") @Valid @RequestParam(value = "externalReferenceID", required = false) String externalReferenceID,
@ApiParam(value = "externalReferenceId") @Valid @RequestParam(value = "externalReferenceId", required = false) String externalReferenceId,
@ApiParam(value = "externalReferenceSource") @Valid @RequestParam(value = "externalReferenceSource", required = false) String externalReferenceSource,
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/io/swagger/model/FilterBy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.swagger.model;

public class FilterBy {

private String filterOn;
private String value;

public String getFilterOn() {
return filterOn;
}

public void setFilterOn(String filterOn) {
this.filterOn = filterOn;
}

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}

}
92 changes: 92 additions & 0 deletions src/main/java/io/swagger/model/SearchRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.model.sort.SortBy;
import org.brapi.test.BrAPITestServer.exceptions.BrAPIServerException;
import org.brapi.test.BrAPITestServer.model.dto.EntityColumnNameAndType;
import org.brapi.test.BrAPITestServer.model.dto.EntityType;
import org.springframework.http.HttpStatus;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public abstract class SearchRequest {
@JsonIgnore
Expand All @@ -25,6 +31,20 @@ public abstract class SearchRequest {
@JsonProperty("externalReferenceSources")
protected List<String> externalReferenceSources = null;

@JsonProperty("filterBy")
protected List<FilterBy> filterBy = null;

@JsonProperty("sortBy")
protected List<SortBy> sortBy = null;

@JsonIgnore
protected Map<String, String> sortFilterEntityColumnNamesByRequestName = null;

@JsonIgnore
public List<String> getExternalReferenceIds() {
return externalReferenceIds;
}

final public SearchRequest page(Integer page) {
this.page = page;
return this;
Expand Down Expand Up @@ -119,4 +139,76 @@ public void addExternalReferenceItem(String externalReferenceId, String external
}

}

public List<FilterBy> getFilterBy() {
return filterBy;
}

public void setFilterBy(List<FilterBy> filterBy) throws BrAPIServerException {

if (filterBy == null || filterBy.isEmpty()) {
return;
}

Map<String, EntityColumnNameAndType> allowedSortFilterNames = getEntityColAndTypeBySubmittedNameMap();

for (FilterBy filterByItem : filterBy) {

if (filterByItem.getFilterOn() == null || filterByItem.getFilterOn().isEmpty()) {
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, "filterOn attribute not provided in element of filterBy list.");
}

if (filterByItem.getValue() == null || filterByItem.getValue().isEmpty()) {
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, "value attribute not provided in element of filterBy list.");
}

EntityColumnNameAndType entityColumnNameAndType = allowedSortFilterNames.get(filterByItem.getFilterOn());

if (entityColumnNameAndType == null) {
throw new BrAPIServerException(HttpStatus.BAD_REQUEST,
String.format("Supplied filterColumn [%s] not available in allowed names [%s]", filterByItem.getFilterOn(), allowedSortFilterNames.keySet())
);
}

if (entityColumnNameAndType.getEntityType() == EntityType.BOOLEAN) {
// TODO: Add support for this when it becomes relevant for BI or when there is time.
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, String.format("Filtering not implemented for column name [%s] with associated data type [%s]", entityColumnNameAndType.getEntityColumnName(), EntityType.BOOLEAN));
}
}
this.filterBy = filterBy;
}

public List<SortBy> getSortByElements() {
return sortBy;
}

public void setSortBy(List<SortBy> sortBy) throws BrAPIServerException {

if (sortBy == null || sortBy.isEmpty()) {
return;
}

Map<String, EntityColumnNameAndType> allowedSortFilterNames = getEntityColAndTypeBySubmittedNameMap();

for (SortBy sortByItem : sortBy) {
if (sortByItem.getSortedOn() == null || sortByItem.getSortedOn().isEmpty()) {
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, "sortedOn attribute not provided in element of sortBy list");
}

EntityColumnNameAndType sortColumnEntityNameAndType = getEntityColAndTypeBySubmittedNameMap().get(sortByItem.getSortedOn());

if (sortColumnEntityNameAndType == null) {
throw new BrAPIServerException(HttpStatus.BAD_REQUEST,
String.format("Supplied sortColumn [%s] not available in allowed names [%s]", sortByItem.getSortedOn(), allowedSortFilterNames.keySet())
);
}
}

this.sortBy = sortBy;
}

@JsonIgnore
public Map<String, EntityColumnNameAndType> getEntityColAndTypeBySubmittedNameMap() throws BrAPIServerException {
throw new BrAPIServerException(HttpStatus.BAD_REQUEST, String.format("Sort/Filtering not implemented for %s", this.getClass().getSimpleName()));
}
}
56 changes: 0 additions & 56 deletions src/main/java/io/swagger/model/core/SortBy.java

This file was deleted.

65 changes: 28 additions & 37 deletions src/main/java/io/swagger/model/core/StudySearchRequest.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,36 @@
package io.swagger.model.core;

import java.util.Map;
import java.util.Objects;

import com.fasterxml.jackson.annotation.JsonProperty;

import io.swagger.model.SearchRequest;
import org.brapi.test.BrAPITestServer.model.dto.EntityColumnNameAndType;
import org.brapi.test.BrAPITestServer.model.dto.EntityType;

import java.util.ArrayList;
import java.util.List;

public class StudySearchRequest extends SearchRequest {

// Key - allowed sort or field filter name for this entity
// Value = entity field name and type that represents the submitted field. Used later on in query building.
private static final Map<String, EntityColumnNameAndType> ALLOWED_SORT_AND_FILTER_FIELDS =
Map.ofEntries(
Map.entry("germplasmDbId", new EntityColumnNameAndType("*obsunit.germplasm.id", EntityType.UUID)),
Map.entry("locationDbId", new EntityColumnNameAndType("location.id", EntityType.UUID)),
Map.entry("observationVariableDbId", new EntityColumnNameAndType("*observation.observationVariable.id", EntityType.UUID)),
Map.entry("programDbId", new EntityColumnNameAndType("trial.program.id", EntityType.UUID)),
Map.entry("programName", new EntityColumnNameAndType("trial.program.name", EntityType.TEXT)),
Map.entry("seasonDbId", new EntityColumnNameAndType("*season.id", EntityType.UUID)),
Map.entry("studyDbId", new EntityColumnNameAndType("id", EntityType.UUID)),
Map.entry("studyLocation", new EntityColumnNameAndType("location.id", EntityType.UUID)),
Map.entry("trialDbId", new EntityColumnNameAndType("trial.id", EntityType.UUID)),
Map.entry("studyType", new EntityColumnNameAndType("studyName", EntityType.TEXT)),
Map.entry("studyName", new EntityColumnNameAndType("studyName", EntityType.TEXT))
);

@JsonProperty("commonCropNames")
private List<String> commonCropNames = null;

Expand Down Expand Up @@ -54,12 +76,6 @@ public class StudySearchRequest extends SearchRequest {
@JsonProperty("seasonDbIds")
private List<String> seasonDbIds = null;

@JsonProperty("sortBy")
private SortBy sortBy = null;

@JsonProperty("sortOrder")
private SortOrder sortOrder = null;

@JsonProperty("studyCodes")
private List<String> studyCodes = null;

Expand Down Expand Up @@ -376,32 +392,6 @@ public void setSeasonDbIds(List<String> seasonDbIds) {
this.seasonDbIds = seasonDbIds;
}

public StudySearchRequest sortBy(SortBy sortBy) {
this.sortBy = sortBy;
return this;
}

public SortBy getSortBy() {
return sortBy;
}

public void setSortBy(SortBy sortBy) {
this.sortBy = sortBy;
}

public StudySearchRequest sortOrder(SortOrder sortOrder) {
this.sortOrder = sortOrder;
return this;
}

public SortOrder getSortOrder() {
return sortOrder;
}

public void setSortOrder(SortOrder sortOrder) {
this.sortOrder = sortOrder;
}

public StudySearchRequest studyCodes(List<String> studyCodes) {
this.studyCodes = studyCodes;
return this;
Expand Down Expand Up @@ -492,7 +482,6 @@ public boolean equals(java.lang.Object o) {
&& Objects.equals(this.active, studySearchRequest.active)
&& Objects.equals(this.seasonDbIds, studySearchRequest.seasonDbIds)
&& Objects.equals(this.sortBy, studySearchRequest.sortBy)
&& Objects.equals(this.sortOrder, studySearchRequest.sortOrder)
&& Objects.equals(this.studyCodes, studySearchRequest.studyCodes)
&& Objects.equals(this.studyPUIs, studySearchRequest.studyPUIs)
&& Objects.equals(this.studyTypes, studySearchRequest.studyTypes) && super.equals(o);
Expand All @@ -503,7 +492,7 @@ public int hashCode() {
return Objects.hash(commonCropNames, programDbIds, programNames, trialDbIds, trialNames, studyDbIds, studyNames,
locationDbIds, locationNames, germplasmDbIds, germplasmNames, observationVariableDbIds,
observationVariableNames, externalReferenceIds, externalReferenceSources, active, seasonDbIds, sortBy,
sortOrder, studyCodes, studyPUIs, studyTypes, super.hashCode());
studyCodes, studyPUIs, studyTypes, super.hashCode());
}

@Override
Expand All @@ -529,7 +518,6 @@ public String toString() {
sb.append(" active: ").append(toIndentedString(active)).append("\n");
sb.append(" seasonDbIds: ").append(toIndentedString(seasonDbIds)).append("\n");
sb.append(" sortBy: ").append(toIndentedString(sortBy)).append("\n");
sb.append(" sortOrder: ").append(toIndentedString(sortOrder)).append("\n");
sb.append(" studyCodes: ").append(toIndentedString(studyCodes)).append("\n");
sb.append(" studyPUIs: ").append(toIndentedString(studyPUIs)).append("\n");
sb.append(" studyTypes: ").append(toIndentedString(studyTypes)).append("\n");
Expand Down Expand Up @@ -583,8 +571,6 @@ public Integer getTotalParameterCount() {
count += this.seasonDbIds.size();
if (this.sortBy != null)
count += 1;
if (this.sortOrder != null)
count += 1;
if (this.studyCodes != null)
count += this.studyCodes.size();
if (this.studyPUIs != null)
Expand All @@ -593,4 +579,9 @@ public Integer getTotalParameterCount() {
count += this.studyTypes.size();
return count;
}

@Override
public Map<String, EntityColumnNameAndType> getEntityColAndTypeBySubmittedNameMap() {
return ALLOWED_SORT_AND_FILTER_FIELDS;
}
}
Loading
Loading