Taxonomy2.java
/**
* Copyright 2014 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.model.genesys;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.genesys.blocks.model.AuditedVersionedModel;
import org.genesys.server.api.model.Api1Constants;
import org.genesys.server.model.GlobalModel;
import org.genesys.server.model.grin.TaxonomySpecies;
import org.hibernate.annotations.Type;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonProperty.Access;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
@Cacheable
@Entity
// Add index on all fields
@Table(name = "taxonomy2", uniqueConstraints = { @UniqueConstraint(name="UK_taxonomy2", columnNames = { "genus", "species", "spAuthor", "subtaxa", "subtAuthor" }) })
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Taxonomy2.class)
@Getter
@Setter
@NoArgsConstructor
public class Taxonomy2 extends AuditedVersionedModel implements GlobalModel {
private static final long serialVersionUID = 8881324404490162933L;
@Column(length = 500)
private String rdfUri;
@Column(nullable = false, length = 100)
@JsonProperty(value = Api1Constants.Accession.GENUS)
private String genus;
@Column(nullable = false, length = 100)
@JsonProperty(value = Api1Constants.Accession.SPECIES)
private String species;
@Column(length = 25)
private String family;
@Column(nullable = false, length = 100)
@JsonProperty(value = Api1Constants.Accession.SPAUTHOR)
private String spAuthor;
@Column(nullable = false, length = 100)
@Field(type = FieldType.Text)
@JsonProperty(value = Api1Constants.Accession.SUBTAXA)
private String subtaxa;
@Column(nullable = false, length = 100)
@JsonProperty(value = Api1Constants.Accession.SUBTAUTHOR)
private String subtAuthor;
@Column(nullable = false)
@Lob
@Type(type = "org.hibernate.type.TextType")
private String taxonName;
private Long taxGenus;
private Long taxSpecies;
@Transient
@Field(type = FieldType.Keyword)
@JsonInclude
private String genusSpecies;
@ManyToOne(cascade = {}, fetch = FetchType.EAGER, optional = true)
@JoinColumn(name = "grinTaxonomySpecies")
@JsonProperty(access = Access.READ_ONLY)
@Field(type = FieldType.Object)
@JsonIgnoreProperties({ "currentTaxonomySpecies", "taxonomyGenus" })
private TaxonomySpecies grinTaxonomySpecies;
@ManyToOne(cascade = {}, fetch = FetchType.EAGER, optional = true)
@JoinColumn(name = "currentTaxonomySpecies")
@JsonProperty(access = Access.READ_ONLY)
@Field(type = FieldType.Object)
@JsonIgnoreProperties({ "currentTaxonomySpecies", "taxonomyGenus" })
private TaxonomySpecies currentTaxonomySpecies;
@ManyToOne(cascade = {}, fetch = FetchType.EAGER, optional = true)
@JoinColumn(name = "overrideTaxonomySpecies")
@JsonIgnore
private TaxonomySpecies overrideTaxonomySpecies;
@OneToMany(cascade = {}, fetch = FetchType.LAZY, mappedBy = "taxonomy")
@JsonIgnore
private List<Accession> accessions;
public Taxonomy2(Taxonomy2 taxonomy) {
if (taxonomy != null) {
this.genus = taxonomy.genus;
this.species = taxonomy.species;
this.spAuthor = taxonomy.spAuthor;
this.subtaxa = taxonomy.subtaxa;
this.subtAuthor = taxonomy.subtAuthor;
}
}
@PrePersist
private void prePersist() {
this.taxonName = getTaxonName();
}
public String getGenusSpecies() {
return this.genus + " " + this.species;
}
public String getTaxonName() {
final StringBuilder sb = new StringBuilder();
sb.append(genus).append(" ").append(species);
if (StringUtils.isNotBlank(spAuthor)) {
sb.append(" ").append(spAuthor);
}
if (StringUtils.isNotBlank(subtaxa)) {
sb.append(" ").append(subtaxa);
}
if (StringUtils.isNotBlank(subtAuthor)) {
sb.append(" ").append(subtAuthor);
}
return sb.toString();
}
public String getTaxonNameHtml() {
final StringBuilder sb = new StringBuilder();
sb.append("<i>").append(genus).append("</i>");
if (species.equals("sp.") || species.equals("spp.")) {
sb.append(" ").append(species);
} else {
sb.append(" <i>").append(species).append("</i>");
}
if (StringUtils.isNotBlank(spAuthor)) {
sb.append(" ").append(spAuthor);
}
if (StringUtils.isNotBlank(subtaxa)) {
sb.append(" ").append(getSubtaxaHtml());
if (StringUtils.isNotBlank(subtAuthor)) {
sb.append(" ").append(subtAuthor);
}
}
return sb.toString();
}
public String getSubtaxaHtml() {
if (StringUtils.isNotBlank(subtaxa)) {
final StringBuilder sb = new StringBuilder();
final AtomicBoolean inLatin = new AtomicBoolean(false);
Arrays.stream(subtaxa.split("\\s+")).forEach((part) -> {
if (part.endsWith(".") || part.toLowerCase().equals("group")) {
sb.append(" ").append(part);
inLatin.set(true);
} else {
if (inLatin.get()) {
sb.append(" <i>").append(part).append("</i>");
} else {
sb.append(" ").append(part);
}
}
});
return sb.toString().trim().replaceAll("</i> <i>", " ");
}
return null;
}
public void setTaxonName(String taxonName) {
// Ignore what they provide
this.taxonName = getTaxonName();
}
// public List<CropTaxonomy> getCropTaxonomies() {
// return cropTaxonomies;
// }
//
// public void setCropTaxonomies(List<CropTaxonomy> cropTaxonomies) {
// this.cropTaxonomies = cropTaxonomies;
// }
public boolean sameAs(Taxonomy2 taxonomy) {
return taxonomy == null ? false : getId().equals(taxonomy.getId());
}
public Long getTaxGenus() {
return this.taxGenus == null ? this.getId() : this.taxGenus;
}
public Long getTaxSpecies() {
return this.taxSpecies == null ? this.getId() : this.taxSpecies;
}
@Override
public String toString() {
return MessageFormat.format("Tax id={0} taxonName={1} genus={2} sp={3} spauthor={4} subtaxa={5} subtauthor={6}", getId(), getTaxonName(), genus, species,
spAuthor, subtaxa, subtAuthor);
}
/**
* Clean up nulls and stuff...
*
* @return
*/
public Taxonomy2 sanitize() {
genus = StringUtils.trimToEmpty(genus);
species = StringUtils.trimToEmpty(species);
spAuthor = StringUtils.trimToEmpty(spAuthor);
subtaxa = StringUtils.trimToEmpty(subtaxa);
subtAuthor = StringUtils.trimToEmpty(subtAuthor);
if (StringUtils.isBlank(species) || "sp".equalsIgnoreCase(species) || "spp".equalsIgnoreCase(species) || "spp.".equalsIgnoreCase(species)) {
species = "sp.";
}
// Force blank subtAuthor when subtaxa is blank
if (StringUtils.isBlank(subtaxa)) {
subtAuthor = "";
}
return this;
}
public boolean equalTo(Taxonomy2 other) {
if (other == null) {
return false;
}
if (! StringUtils.equalsIgnoreCase(genus, other.genus)) {
return false;
}
if (! StringUtils.equalsIgnoreCase(species, other.species)) {
return false;
}
if (! StringUtils.equalsIgnoreCase(spAuthor, other.spAuthor)) {
return false;
}
if (! StringUtils.equalsIgnoreCase(subtaxa, other.subtaxa)) {
return false;
}
if (! StringUtils.equalsIgnoreCase(subtAuthor, other.subtAuthor)) {
return false;
}
return true;
}
@Override
public boolean canEqual(Object other) {
return other instanceof Taxonomy2;
}
}