InstituteFilter.java

/*
 * Copyright 2018 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.genesys.server.service.filter;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.genesys.blocks.model.filters.BasicModelFilter;
import org.genesys.blocks.model.filters.StringFilter;
import org.genesys.blocks.util.CurrentApplicationContext;
import org.genesys.server.model.filters.PartnerFilter;
import org.genesys.server.model.impl.FaoInstitute;
import org.genesys.server.model.impl.QFaoInstitute;
import org.genesys.server.service.PGRFANetworkService;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.querydsl.core.types.Predicate;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.commons.collections4.CollectionUtils;

/**
 * Filter for {@link FaoInstitute}.
 */
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
@Accessors(fluent = true)
@Schema(description = "Filtering criteria to apply to institute records in the database."
	+ "\n\nEach individual filter property can also be set to null or omitted, meaning that it should not be applied."
)
public class InstituteFilter extends BasicModelFilter<InstituteFilter, FaoInstitute, QFaoInstitute> implements IFullTextFilter {

	private static final long serialVersionUID = 4754504385073612669L;

	/** Any text. */
	@Schema(example = "IITA", description = "Keywords to use in a full-text search across the institute database. Whenever possible, use any of the other filtering options for better results. Full-text search is not available in nested filters!")
	@JsonProperty("_text")
	public String _text;

	/** The code. */
	@ArraySchema(schema = @Schema(description = "FAO WIEWS institute code", example = "MEX002"), arraySchema = @Schema(example = "NGA039, MEX002", description = "Match institutes by their FAO WIEWS institute codes."))
	public Set<String> code;
	
	/** The country. */
	public CountryFilter country;
	
	/** The name. */
	public StringFilter fullName;

	/** The accessions. */
	@Schema(description = "Use value true to match only institutes that have accessions in Genesys, false for those that do not have data in Genesys, use null (or omit altogether) if you do not care.")
	public Boolean accessions;

	/** The allowMaterialRequests. */
	@Schema(description = "Filter for institutes that allow requesting for material via Genesys.")
	public Boolean allowMaterialRequests;

	/** The networks. */
	public Set<String> networks;

	/** The owner. */
	public PartnerFilter owner;

	/**
	 * Builds the query.
	 *
	 * @return the predicate
	 */
	@Override
	public List<Predicate> collectPredicates() {
		return collectPredicates(QFaoInstitute.faoInstitute);
	}

	/**
	 * Builds the query.
	 *
	 * @param institute the institute
	 * @return the predicate
	 */
	@Override
	public List<Predicate> collectPredicates(QFaoInstitute institute) {
		final List<Predicate> predicates = super.collectSuperPredicates(institute, institute._super);

		if (code != null && !code.isEmpty()) {
			// predicates.add(institute.code.isNotNull());
			predicates.add(institute.code.in(code()));
		}
		if (country != null) {
			predicates.add(country.nestedPredicate(institute.country()));
		}
		if (fullName != null) {
			predicates.add(fullName.buildQuery(institute.fullName));
		}
		if (accessions != null) {
			if (accessions) {
				predicates.add(institute.accessionCount.gt(0));
			} else {
				predicates.add(institute.accessionCount.eq(0L));
			}
		}
		if (allowMaterialRequests != null) {
			predicates.add(institute.allowMaterialRequests.eq(allowMaterialRequests));
		}
		if (owner != null) {
			predicates.add(owner.nestedPredicate(institute.owner()));
		}
		
		if (CollectionUtils.isNotEmpty(networks)) {
			Set<Long> networkMembers = getNetworkMemberIds(networks);
			predicates.add(institute.id.in(networkMembers));
		}

		return predicates;
	}

	@Override
	public String get_text() {
		return _text;
	}

	private Set<Long> getNetworkMemberIds(Set<String> slugs) {
		PGRFANetworkService networkService = CurrentApplicationContext.getContext().getBean(PGRFANetworkService.class);
		return networkService.getMembers(slugs).stream().map(FaoInstitute::getId).collect(Collectors.toSet());
	}

	public CountryFilter country() {
		if (this.country == null) {
			return this.country = new CountryFilter();
		} else {
			return this.country;
		}
	}
	
	@JsonGetter("code")
	public Set<String> code() {
		return code != null ? code.stream().map(String::toUpperCase).collect(Collectors.toSet()) : Collections.emptySet();
	}
}