PDCICalculator.java

/*
 * Copyright 2021 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.util;

import java.util.Collection;

import org.apache.commons.lang3.StringUtils;
import org.genesys.server.model.genesys.Accession;
import org.genesys.server.model.genesys.AccessionAlias;
import org.genesys.server.model.genesys.AccessionCollect;
import org.genesys.server.model.genesys.AccessionId;
import org.genesys.server.model.genesys.PDCI;
import org.genesys.server.model.genesys.Taxonomy2;
import org.genesys.server.model.genesys.AccessionAlias.AliasType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Calculates PDCI value for an accession.
 * 
 * <p>
 * Theo van Hintum, Frank Menting and Elisabeth van Strien (2011). <b>Quality
 * indicators for passport data in ex situ genebanks.</b> Plant Genetic
 * Resources, 9, pp 478-485.
 * 
 * doi:10.1017/S1479262111000682
 * </p>
 */
public class PDCICalculator {
	public static final Logger LOG = LoggerFactory.getLogger(PDCICalculator.class);

	/**
	 * Updates and returns the updated PDCI object for the accession.
	 * 
	 * @param pdci the PDCI object
	 * @param accession accession on which PDCI is calculated
	 * @return the updated PDCI object
	 */
	public static PDCI updatePdci(PDCI pdci, Accession accession) {
		pdci.reset();

		independentDescriptors(pdci, accession);

		switch (accession.getSampStat() == null ? -1 : accession.getSampStat() / 100) {
		case 1:
		case 2:
			wildOrWeedy(pdci, accession);
			break;

		case 3:
			landrace(pdci, accession);
			break;

		case 4:
			breedingMaterial(pdci, accession);
			break;

		case 5:
			cultivar(pdci, accession);
			break;
			
		default:
			otherTypes(pdci, accession);
		}

		return pdci;
	}

	private static void independentDescriptors(PDCI pdci, Accession accession) {
		AccessionId accessionId = accession.getAccessionId();

		taxonomic(pdci, accession.getTaxonomy());

		if (StringUtils.isNotBlank(accession.getCropName())) {
			pdci.setCropName(45);
		}

		if (StringUtils.isNotBlank(accession.getAcquisitionDate())) {
			if (MCPDUtil.isMcpdDate(accession.getAcquisitionDate())) {
				pdci.setAcqDate(10);
			} else {
				pdci.setAcqDate(5);
			}
		}
		if (accession.getSampStat() != null) {
			pdci.setSampStat(80);
		}
		if (StringUtils.isNotBlank(accession.getDonorCode())) {
			if (MCPDUtil.isWiewsCode(accession.getDonorCode())) {
				pdci.setDonorCode(40);
			} else {
				pdci.setDonorCode(20);
			}
		}
		if (StringUtils.isNotBlank(accession.getDonorNumb())) {
			if (StringUtils.isBlank(accession.getDonorCode()) && StringUtils.isBlank(accession.getDonorName())) {
				pdci.setDonorNumb(20);
			} else {
				pdci.setDonorNumb(40);
			}
		}

		if (names(accessionId.getAliases(), AliasType.OTHERNUMB)) {
			pdci.setOtherNumb(35);
		}

		if (accessionId.getDuplSite() != null && accessionId.getDuplSite().size() > 0) {
			if (accessionId.getDuplSite().stream().filter(code -> !MCPDUtil.isWiewsCode(code)).count() == 0) {
				pdci.setDuplSite(30);
			} else {
				pdci.setDuplSite(15);
			}
		} else {
			// Missing DUPLINSTNAME in Genesys, would add 15
			pdci.setDuplInstName(0);
		}

		if (accessionId.getStorage() != null && accessionId.getStorage().size() > 0) {
			pdci.setStorage(15);
		}

		if (StringUtils.isNotBlank(accession.getDonorName())) {
			if (StringUtils.isBlank(accession.getDonorCode())) {
				pdci.setDonorName(20);
			} else {
				pdci.setDonorName(0);
			}
		}

		if (accession.getAcceUrl() != null) {
			pdci.setAcceUrl(40);
		}

		if (accession.getMlsStatus() != null) {
			pdci.setMlsStat(15);
		}
	}

	private static void taxonomic(PDCI pdci, Taxonomy2 taxonomy) {
		if (taxonomy != null) {
			if (!StringUtils.isBlank(taxonomy.getGenus())) {
				pdci.setGenus(120);
				if (!StringUtils.isBlank(taxonomy.getSpecies()) && !StringUtils.equalsIgnoreCase("sp.", taxonomy.getSpecies())) {
					pdci.setSpecies(80);

					if (!StringUtils.isBlank(taxonomy.getSpAuthor())) {
						pdci.setSpAuthor(5);
					}
					if (!StringUtils.isBlank(taxonomy.getSubtaxa())) {
						pdci.setSubTaxa(40);

						if (!StringUtils.isBlank(taxonomy.getSubtAuthor())) {
							pdci.setSubtAuthor(5);
						}
					}
				}
			}
		}
	}

	private static void wildOrWeedy(PDCI pdci, Accession accession) {
		AccessionId accessionId = accession.getAccessionId();

		AccessionCollect coll = accessionId.getColl();

		if (accession.getCountryOfOrigin() != null) {
			pdci.setOrigCty(80);
		}

		boolean hasLatLng = false;

		if (accessionId.getLatitude() != null && accessionId.getLongitude() != null) {
			if (accessionId.getLatitude() < -90 || accessionId.getLatitude() > 90 || accessionId.getLongitude() < -180 || accessionId.getLongitude() > 180) {
				// Ignore coordinates
			} else {
				pdci.setLatitude(60);
				pdci.setLongitude(60);
				hasLatLng = true;
			}
		}

		if (accessionId.getElevation() != null) {
			pdci.setElevation(20);
		}

		if (coll != null) {
			if (StringUtils.isNotBlank(coll.getCollSite())) {
				if (hasLatLng)
					pdci.setCollSite(20);
				else
					pdci.setCollSite(70);
			}

			if (StringUtils.isNotBlank(coll.getCollDate())) {
				if (MCPDUtil.isMcpdDate(coll.getCollDate())) {
					pdci.setCollDate(30);
				} else {
					pdci.setCollDate(15);
				}
			}
			if (coll.getCollSrc() != null) {
				pdci.setCollSrc(30);
			}

			if (StringUtils.isNotBlank(coll.getCollNumb())) {
				pdci.setCollNumb(60);
			}
			if (coll.getCollCode() != null && coll.getCollCode().size() > 0) {
				pdci.setCollCode(40);
			} else {
				if (coll.getCollName() != null && coll.getCollName().size() > 0) {
					pdci.setCollName(20);
				}
			}
		}
	}

	private static void landrace(PDCI pdci, Accession accession) {
		AccessionId accessionId = accession.getAccessionId();
		AccessionCollect coll = accessionId.getColl();

		if (accession.getCountryOfOrigin() != null) {
			pdci.setOrigCty(80);
		}

		boolean hasLatLng = false;

		if (accessionId.getLatitude() != null && accessionId.getLongitude() != null) {
			pdci.setLatitude(40);
			pdci.setLongitude(40);
			hasLatLng = true;
		}

		if (accessionId.getElevation() != null) {
			pdci.setElevation(15);
		}

		if (StringUtils.isNotBlank(accession.getAncest())) {
			pdci.setAncest(10);
		}

		if (names(accession.getAccessionId().getAliases(), AliasType.ACCENAME)) {
			pdci.setAcceName(50);
		}

		if (coll != null) {
			if (StringUtils.isNotBlank(coll.getCollSite())) {
				if (hasLatLng)
					pdci.setCollSite(15);
				else
					pdci.setCollSite(45);
			}

			if (StringUtils.isNotBlank(coll.getCollDate())) {
				if (MCPDUtil.isMcpdDate(coll.getCollDate())) {
					pdci.setCollDate(30);
				} else {
					pdci.setCollDate(15);
				}
			}

			if (coll.getCollSrc() != null) {
				pdci.setCollSrc(50);
			}

			if (StringUtils.isNotBlank(coll.getCollNumb())) {
				pdci.setCollNumb(40);
			}
			if (coll.getCollCode() != null && coll.getCollCode().size() > 0) {
				pdci.setCollCode(30);
			} else {
				if (coll.getCollName() != null && coll.getCollName().size() > 0) {
					pdci.setCollName(15);
				}
			}
		}
	}

	private static void breedingMaterial(PDCI pdci, Accession accession) {
		AccessionId accessionId = accession.getAccessionId();
		AccessionCollect coll = accessionId.getColl();

		if (accession.getCountryOfOrigin() != null) {
			pdci.setOrigCty(40);
		}

		if (accessionId.getBreederCode() != null && accessionId.getBreederCode().size() > 0) {
			if (accessionId.getBreederCode().stream().filter(code -> !MCPDUtil.isWiewsCode(code)).count() == 0) {
				pdci.setBredCode(110);
			} else {
				pdci.setBredCode(55);
			}
		}

		if (StringUtils.isNotBlank(accession.getAncest())) {
			pdci.setAncest(150);
		}

		if (names(accession.getAccessionId().getAliases(), AliasType.ACCENAME)) {
			pdci.setAcceName(80);
		}

		if (coll != null) {
			if (StringUtils.isNotBlank(coll.getCollSite())) {
			}

			if (StringUtils.isNotBlank(coll.getCollDate())) {
			}

			if (coll.getCollSrc() != null) {
				pdci.setCollSrc(20);
			}

			if (StringUtils.isNotBlank(coll.getCollNumb())) {
			}

			if (coll.getCollCode() != null && coll.getCollCode().size() > 0) {
			}
		}
	}

	private static void cultivar(PDCI pdci, Accession accession) {
		AccessionId accessionId = accession.getAccessionId();
		AccessionCollect coll = accessionId.getColl();

		if (accession.getCountryOfOrigin() != null) {
			pdci.setOrigCty(40);
		}

		if (accessionId.getBreederCode() != null && accessionId.getBreederCode().size() > 0) {
			if (accessionId.getBreederCode().stream().filter(code -> !MCPDUtil.isWiewsCode(code)).count() == 0) {
				pdci.setBredCode(80);
			} else {
				pdci.setBredCode(40);
			}
		}

		if (StringUtils.isNotBlank(accession.getAncest())) {
			pdci.setAncest(100);
		}

		if (names(accession.getAccessionId().getAliases(), AliasType.ACCENAME)) {
			pdci.setAcceName(160);
		}

		if (coll != null) {
			if (StringUtils.isNotBlank(coll.getCollSite())) {
			}

			if (StringUtils.isNotBlank(coll.getCollDate())) {
			}

			if (coll.getCollSrc() != null) {
				pdci.setCollSrc(20);
			}

			if (StringUtils.isNotBlank(coll.getCollNumb())) {
			}

			if (coll.getCollCode() != null && coll.getCollCode().size() > 0) {
			}
		}
	}

	private static void otherTypes(PDCI pdci, Accession accession) {
		AccessionId accessionId = accession.getAccessionId();
		AccessionCollect coll = accessionId.getColl();

		if (accession.getCountryOfOrigin() != null) {
			pdci.setOrigCty(40);
		}

		boolean hasLatLng = false;

		if (accessionId.getLatitude() != null && accessionId.getLongitude() != null) {
			pdci.setLatitude(15);
			pdci.setLongitude(15);
			hasLatLng = true;
		}

		if (accessionId.getElevation() != null) {
			pdci.setElevation(5);
		}

		if (accessionId.getBreederCode() != null && accessionId.getBreederCode().size() > 0) {
			if (accessionId.getBreederCode().stream().filter(code -> !MCPDUtil.isWiewsCode(code)).count() == 0) {
				pdci.setBredCode(10);
			} else {
				pdci.setBredCode(5);
			}
		}

		if (StringUtils.isNotBlank(accession.getAncest())) {
			pdci.setAncest(40);
		}

		if (names(accession.getAccessionId().getAliases(), AliasType.ACCENAME)) {
			pdci.setAcceName(40);
		}

		if (coll != null) {
			if (StringUtils.isNotBlank(coll.getCollSite())) {
				if (hasLatLng)
					pdci.setCollSite(10);
				else
					pdci.setCollSite(20);
			}

			if (StringUtils.isNotBlank(coll.getCollDate())) {
				if (MCPDUtil.isMcpdDate(coll.getCollDate())) {
					pdci.setCollDate(10);
				} else {
					pdci.setCollDate(5);
				}
			}

			if (coll.getCollSrc() != null) {
				pdci.setCollSrc(25);
			}

			if (StringUtils.isNotBlank(coll.getCollNumb())) {
				pdci.setCollNumb(20);
			}
			if (coll.getCollCode() != null && coll.getCollCode().size() > 0) {
				pdci.setCollCode(20);
			} else {
				if (coll.getCollName() != null && coll.getCollName().size() > 0) {
					pdci.setCollName(10);
				}
			}
		}
	}

	private static boolean names(Collection<AccessionAlias> aliases, AliasType type) {
		if (aliases == null || aliases.size() == 0)
			return false;

		for (AccessionAlias alias : aliases) {
			if (alias.getAliasType() == type) {
				return true;
			}
		}
		return false;
	}

}