AccessionFilter.java
/*
* Copyright 2020 Global Crop Diversity Trust
*
* 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.gringlobal.service.filter;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.genesys.blocks.model.filters.TemporalFilter;
import org.genesys.blocks.model.filters.NumberFilter;
import org.genesys.blocks.model.filters.StringFilter;
import org.genesys.blocks.util.CurrentApplicationContext;
import org.gringlobal.api.exception.InvalidApiUsageException;
import org.gringlobal.model.Accession;
import org.gringlobal.model.QAccession;
import org.gringlobal.model.QAccessionAction;
import org.gringlobal.model.QAccessionSource;
import com.querydsl.core.types.Predicate;
import org.gringlobal.model.QCropTraitObservation;
import org.gringlobal.model.QInventory;
import org.gringlobal.model.QSourceDescObservation;
import org.gringlobal.persistence.AccessionInvGroupMapRepository;
/**
* Filters for {@link Accession}
*/
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
@Accessors(fluent = true)
public class AccessionFilter extends CooperatorOwnedModelFilter<AccessionFilter, Accession> implements IFullTextFilter {
private static final long serialVersionUID = -7684502726900427124L;
/** Any text. */
public String _text;
/** The doi. */
public Set<String> doi;
/** The acce preferred name */
public StringFilter preferredName;
/** The acce numb. */
public Set<String> accessionNumber;
/** The acce numb part1. */
public StringFilter accessionNumberPart1;
/** The acce numb part2. */
public NumberFilter<Long> accessionNumberPart2;
/** The acce numb part3. */
public StringFilter accessionNumberPart3;
/** The backup location1 site. */
public SiteFilter backupLocation1Site;
/** The backup location2 site. */
public SiteFilter backupLocation2Site;
/** The improvement status code. */
public Set<String> improvementStatusCode;
/** The MLS status. */
public Set<String> mlsStatus;
/** The initial received date. */
public TemporalFilter<Date> initialReceivedDate;
/** The initial received date code. */
public Set<String> initialReceivedDateCode;
/** The initial received form code. */
public Set<String> initialReceivedFormCode;
/** is backed up */
public Boolean backedUp;
/** is core */
public Boolean core;
/** is web visible */
public Boolean webVisible;
/** The life form code. */
public Set<String> lifeFormCode;
/** The note. */
public StringFilter note;
/** The reproductive uniformity code. */
public Set<String> reproductiveUniformityCode;
/** The status code. */
public Set<String> statusCode;
/** The taxonomy species filter. */
public TaxonomySpeciesFilter taxonomySpecies;
/** Accession sources */
public AccessionSourceFilter sources;
/** Site */
public SiteFilter site;
/** The Accession inventory group ids. */
public Set<Long> accessionInvGroup;
/** The Accession actions */
public AccessionActionFilter accessionActions;
/** The Accession inventories */
public InventoryFilter inventories;
/** The AccessionIprs */
public AccessionIprFilter accessionIprs;
/** The curation type code. */
public Set<String> curationTypeCode;
/** The source observations values. */
public List<SourceDescObservationFilter.SourceDescValueFilter> sourceObservations;
/** The crop traits value */
public List<CropTraitObservationFilter.CropTraitValueFilter> cropTraits;
/** Accession names */
public StringFilter plantName;
/** The exploration */
public ExplorationFilter exploration;
/** The collection */
public Set<String> collectionCode;
/** The attachment */
public AccessionInvAttachFilter accessionInvAttach;
/**
* Builds the query.
*
* @return the predicate
*/
@Override
public List<Predicate> collectPredicates() {
return collectPredicates(QAccession.accession);
}
/**
* Builds the query.
*
* @param accession the accession
* @return the predicate
*/
public List<Predicate> collectPredicates(QAccession accession) {
final List<Predicate> predicates = super.collectPredicates(accession, accession._super);
if (CollectionUtils.isNotEmpty(doi)) {
predicates.add(accession.doi.in(doi));
}
if (CollectionUtils.isNotEmpty(accessionNumber)) {
predicates.add(accession.accessionNumber.in(accessionNumber));
}
if (preferredName != null) {
predicates.add(preferredName.buildQuery(accession.preferredName));
}
if (accessionNumberPart1 != null) {
predicates.add(accessionNumberPart1.buildQuery(accession.accessionNumberPart1));
}
if (accessionNumberPart2 != null) {
predicates.add(accessionNumberPart2.buildQuery(accession.accessionNumberPart2));
}
if (accessionNumberPart3 != null) {
predicates.add(accessionNumberPart3.buildQuery(accession.accessionNumberPart3));
}
if (site != null) {
predicates.addAll(site.collectPredicates(accession.site()));
}
if (backupLocation1Site != null) {
predicates.addAll(backupLocation1Site.collectPredicates(accession.backupLocation1Site()));
}
if (backupLocation2Site != null) {
predicates.addAll(backupLocation2Site.collectPredicates(accession.backupLocation2Site()));
}
if (CollectionUtils.isNotEmpty(improvementStatusCode)) {
predicates.add(accession.improvementStatusCode.in(improvementStatusCode));
}
if (CollectionUtils.isNotEmpty(mlsStatus)) {
predicates.add(accession.mlsStatus.in(mlsStatus));
}
if (initialReceivedDate != null) {
predicates.add(initialReceivedDate.buildQuery(accession.initialReceivedDate));
}
if (CollectionUtils.isNotEmpty(initialReceivedDateCode)) {
predicates.add(accession.initialReceivedDateCode.in(initialReceivedDateCode));
}
if (CollectionUtils.isNotEmpty(initialReceivedFormCode)) {
predicates.add(accession.initialReceivedFormCode.in(initialReceivedFormCode));
}
if (backedUp != null) {
predicates.add(accession.isBackedUp.eq(convertToString(backedUp)));
}
if (core != null) {
predicates.add(accession.isCore.eq(convertToString(core)));
}
if (webVisible != null) {
predicates.add(accession.isWebVisible.eq(convertToString(webVisible)));
}
if (CollectionUtils.isNotEmpty(lifeFormCode)) {
predicates.add(accession.lifeFormCode.in(lifeFormCode));
}
if (note != null) {
predicates.add(note.buildQuery(accession.note));
}
if (CollectionUtils.isNotEmpty(reproductiveUniformityCode)) {
predicates.add(accession.reproductiveUniformityCode.in(reproductiveUniformityCode));
}
if (CollectionUtils.isNotEmpty(statusCode)) {
predicates.add(accession.statusCode.in(statusCode));
}
if (CollectionUtils.isNotEmpty(curationTypeCode)) {
predicates.add(accession.curationTypeCode.in(curationTypeCode));
}
if (taxonomySpecies != null) {
predicates.addAll(taxonomySpecies.collectPredicates(accession.taxonomySpecies()));
}
if (sources != null) {
var qAccessionSource = new QAccessionSource(accession.accessionSources.getMetadata().getName()); // alias MUST match accession.accessionSources path
predicates.add(nestedFilter(accession.accessionSources, qAccessionSource, qAccessionSource.accession().eq(accession), sources.collectPredicates(qAccessionSource)));
}
if (accessionInvGroup != null) {
predicates.add(accession.inventories.any().id.in(getInventoryMembersOfGroups(accessionInvGroup)));
}
if (accessionActions != null) {
var qAccessionAction = new QAccessionAction(accession.accessionActions.getMetadata().getName());
predicates.add(nestedFilter(accession.accessionActions, qAccessionAction, qAccessionAction.accession().eq(accession), accessionActions.collectPredicates(qAccessionAction)));
}
if (inventories != null) {
predicates.addAll(inventories.collectPredicates(accession.inventories.any()));
}
if (accessionIprs != null) {
predicates.addAll(accessionIprs.collectPredicates(accession.accessionIprs.any()));
}
if (CollectionUtils.isNotEmpty(sourceObservations)) {
if (StringUtils.isNotBlank(_text)) throw new InvalidApiUsageException("_text search is not available when filtering sourceObservations");
predicates.add(accession.id.in(processSourceDescObservations(sourceObservations)));
}
if (CollectionUtils.isNotEmpty(cropTraits)) {
if (StringUtils.isNotBlank(_text)) throw new InvalidApiUsageException("_text search is not available when filtering cropTrats");
predicates.add(accession.id.in(processCropTraitObservations(cropTraits)));
}
if (plantName != null) {
predicates.add(plantName.buildQuery(accession.inventories.any().names.any().plantName));
}
if(exploration != null) {
predicates.addAll(exploration.collectPredicates(accession.exploration()));
}
if (CollectionUtils.isNotEmpty(collectionCode)) {
predicates.add(accession.collectionCode.in(collectionCode));
}
if (accessionInvAttach != null) {
predicates.addAll(accessionInvAttach.collectPredicates(accession.inventories.any().attachments.any()));
}
return predicates;
}
private JPAQuery<Long> processSourceDescObservations(List<SourceDescObservationFilter.SourceDescValueFilter> sourceObservations) {
var jpaQueryFactory = CurrentApplicationContext.getContext().getBean(JPAQueryFactory.class);
JPAQuery<Long> query = null;
int queryNum = 0;
for (var sourceFilter : sourceObservations) {
var qPath = new QSourceDescObservation("sourceObs" + queryNum++);
var predicate = sourceFilter.buildPredicate(qPath);
var sourceDescQuery = jpaQueryFactory.selectDistinct(qPath.accessionSource().accession().id).from(qPath).where(predicate);
if (query != null) {
// Intersection of the two sets of accession.ids
sourceDescQuery.where(qPath.accessionSource().accession().id.in(query));
}
query = sourceDescQuery;
}
return query;
}
private JPAQuery<Long> processCropTraitObservations(List<CropTraitObservationFilter.CropTraitValueFilter> cropTraits) {
var jpaQueryFactory = CurrentApplicationContext.getContext().getBean(JPAQueryFactory.class);
JPAQuery<Long> query = null;
int queryNum = 0;
for (var cropTraitFilter : cropTraits) {
var qPath = new QCropTraitObservation("cropTraitObs" + queryNum++);
var predicate = cropTraitFilter.buildPredicate(qPath);
var traitQuery = jpaQueryFactory.selectDistinct(qPath.inventory().id).from(qPath).where(predicate);
if (query != null) {
// Intersection of the two sets of inventory.ids
traitQuery.where(qPath.inventory().id.in(query));
}
query = traitQuery;
}
var qInventory = QInventory.inventory;
var accessionQuery = jpaQueryFactory.selectDistinct(qInventory.accession().id).from(qInventory).where(qInventory.id.in(query));
return accessionQuery;
}
private List<Long> getInventoryMembersOfGroups(Collection<Long> ids) {
var repository = CurrentApplicationContext.getContext().getBean(AccessionInvGroupMapRepository.class);
return repository.findAllByAccessionInvGroup_IdIn(ids).stream()
.map(groupMap -> groupMap.getInventory().getId())
.collect(Collectors.toList());
}
/**
* Gets the text.
*
* @return the text
*/
@Override
public String get_text() {
return _text;
}
/**
* Id.
*
* @return the set of Ids
*/
public synchronized Set<Long> id() {
if (id == null) {
id = new HashSet<>();
}
return id;
}
/**
* DOI.
*
* @return the set of DOIs
*/
public synchronized Set<String> doi() {
return this.doi == null ? this.doi = new HashSet<>() : this.doi;
}
/**
* The accessionNumbers.
*
* @return the set of accessionNumbers
*/
public synchronized Set<String> accessionNumbers() {
return this.accessionNumber == null ? this.accessionNumber = new HashSet<>() : this.accessionNumber;
}
/**
* Taxonomy species filter.
*
* @return the taxonomy species filter
*/
public synchronized TaxonomySpeciesFilter taxonomySpecies() {
return this.taxonomySpecies == null ? this.taxonomySpecies = new TaxonomySpeciesFilter() : this.taxonomySpecies;
}
}