X-Git-Url: https://dev.e-taxonomy.eu/gitweb/cdmlib.git/blobdiff_plain/3c0b88b272eee69f6a815769b47ccb5b41fd619f..HEAD:/cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/Synonym.java
diff --git a/cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/Synonym.java b/cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/Synonym.java
index f6fabaf95b..c8becc9ddd 100644
--- a/cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/Synonym.java
+++ b/cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/Synonym.java
@@ -1,107 +1,213 @@
/**
* Copyright (C) 2007 EDIT
-* European Distributed Institute of Taxonomy
+* European Distributed Institute of Taxonomy
* http://www.e-taxonomy.eu
-*
+*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* See LICENSE.TXT at the top of this package for the full license terms.
*/
-
package eu.etaxonomy.cdm.model.taxon;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.ManyToOne;
+import javax.persistence.Transient;
+import javax.validation.constraints.NotNull;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlIDREF;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
+import org.hibernate.annotations.Type;
+import org.hibernate.envers.Audited;
+import org.hibernate.search.annotations.ContainedIn;
+import org.hibernate.search.annotations.Indexed;
+import org.springframework.beans.factory.annotation.Configurable;
-import eu.etaxonomy.cdm.model.common.IRelated;
-import eu.etaxonomy.cdm.model.name.TaxonNameBase;
-import eu.etaxonomy.cdm.model.reference.ReferenceBase;
-
-import java.util.*;
-
-import javax.persistence.*;
+import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
+import eu.etaxonomy.cdm.model.name.ITaxonNameBase;
+import eu.etaxonomy.cdm.model.name.TaxonName;
+import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.cdm.strategy.cache.taxon.ITaxonCacheStrategy;
+import eu.etaxonomy.cdm.validation.Level3;
+import eu.etaxonomy.cdm.validation.annotation.HomotypicSynonymsShouldBelongToGroup;
/**
+ * The class for synonyms: these are {@link TaxonBase taxa} the {@link name.TaxonName taxon names}
+ * of which are not used by the {@link TaxonBase#getSec() reference} to designate a real
+ * taxon but are mentioned as taxon names that were oder are used by some other
+ * unspecified references to designate (at least to some extent) the same
+ * particular real taxon. Synonyms that are {@link #getAcceptedTaxon() attached} to an accepted {@link Taxon taxon}
+ * are actually meaningless.
+ * Splitting taxa in "accepted/valid" and "synonyms"
+ * makes it easier to handle particular relationships between
+ * ("accepted/valid") {@link Taxon taxa} on the one hand and ("synonym") taxa
+ * on the other.
+ *
* @author m.doering
- * @version 1.0
- * @created 08-Nov-2007 13:06:55
+ * @since 08-Nov-2007 13:06:55
*/
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "Synonym", propOrder = {
+ "acceptedTaxon",
+ "type",
+})
+@XmlRootElement(name = "Synonym")
@Entity
-public class Synonym extends TaxonBase implements IRelated{
- static Logger logger = Logger.getLogger(Synonym.class);
-
- private Set synonymRelations = new HashSet();
+@Indexed(index = "eu.etaxonomy.cdm.model.taxon.TaxonBase")
+@Audited
+@Configurable
+@HomotypicSynonymsShouldBelongToGroup(groups = Level3.class)
+public class Synonym extends TaxonBase> {
+ private static final long serialVersionUID = 6977221584815363620L;
- public static Synonym NewInstance(TaxonNameBase taxonName, ReferenceBase sec){
- Synonym result = new Synonym();
- result.setName(taxonName);
- result.setSec(sec);
- return result;
- }
-
+ @SuppressWarnings("unused")
+ private static final Logger logger = LogManager.getLogger();
+
+ @XmlElement(name = "acceptedTaxon")
+ @XmlIDREF
+ @XmlSchemaType(name = "IDREF")
+ @ManyToOne(fetch = FetchType.LAZY)
+ @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
+ @ContainedIn
+// @NotEmpty(groups = Level2.class,message="{eu.etaxonomy.cdm.model.taxon.Synonym.noOrphanedSynonyms.message}")
+// @NotNull(groups = Level2.class)
+ private Taxon acceptedTaxon;
+
+ @XmlAttribute(name ="Type")
+ @NotNull
+ @Type(type = "eu.etaxonomy.cdm.hibernate.EnumUserType",
+ parameters = {@org.hibernate.annotations.Parameter(name="enumClass", value="eu.etaxonomy.cdm.model.taxon.SynonymType")}
+ )
+ private SynonymType type = SynonymType.SYNONYM_OF;
+
+//************************************* FACTORY ****************************/
+ /**
+ * @see #NewInstance(TaxonName, Reference)
+ * @param taxonName
+ * @param sec
+ * @return
+ */
+ public static Synonym NewInstance(ITaxonNameBase taxonName, Reference sec){
+ return NewInstance(TaxonName.castAndDeproxy(taxonName), sec);
+ }
+
+ /**
+ * Creates a new synonym instance with
+ * the {@link eu.etaxonomy.cdm.model.name.TaxonName taxon name} used and the {@link eu.etaxonomy.cdm.model.reference.Reference reference}
+ * using it as a synonym and not as an ("accepted/correct") {@link Taxon taxon}.
+ *
+ * @param TAXON_NAME the taxon name used
+ * @param sec the reference using the taxon name
+ * @see #Synonym(TaxonName, Reference)
+ */
+ public static Synonym NewInstance(TaxonName taxonName, Reference sec){
+ Synonym result = new Synonym(taxonName, sec, null);
+ return result;
+ }
+
+ public static Synonym NewInstance(TaxonName taxonName, Reference sec, String secDetail){
+ Synonym result = new Synonym(taxonName, sec, secDetail);
+ return result;
+ }
+
+// ********************* CONSTRUCTORS ******************************/
+
+ //for hibernate use only, *packet* private required by bytebuddy
//TODO should be private, but still produces Spring init errors
- public Synonym(){
- }
-
+ Synonym(){}
- @OneToMany(mappedBy="relatedFrom", fetch=FetchType.EAGER)
- @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})
- public Set getSynonymRelations() {
- return synonymRelations;
- }
- protected void setSynonymRelations(Set synonymRelations) {
- this.synonymRelations = synonymRelations;
- }
- protected void addSynonymRelation(SynonymRelationship synonymRelation) {
- this.synonymRelations.add(synonymRelation);
- }
- protected void removeSynonymRelation(SynonymRelationship synonymRelation) {
- synonymRelation.setSynonym(null);
- Taxon taxon = synonymRelation.getAcceptedTaxon();
- if (taxon != null){
- synonymRelation.setAcceptedTaxon(null);
- taxon.removeSynonymRelation(synonymRelation);
- }
- this.synonymRelations.remove(synonymRelation);
- }
-
-
- /* (non-Javadoc)
- * @see eu.etaxonomy.cdm.model.common.IRelated#addRelationship(eu.etaxonomy.cdm.model.common.RelationshipBase)
- */
- public void addRelationship(SynonymRelationship rel){
- addSynonymRelation(rel);
+ private Synonym(TaxonName taxonName, Reference sec, String secDetail){
+ super(taxonName, sec, secDetail);
}
+//********************** GETTER/SETTER ******************************/
- @Transient
- public Set getAcceptedTaxa() {
- Settaxa=new HashSet();
- for (SynonymRelationship rel:getSynonymRelations()){
- taxa.add(rel.getAcceptedTaxon());
- }
- return taxa;
+ /**
+ * Returns the "accepted/valid" {@link Taxon taxon}
+ *
+ */
+ public Taxon getAcceptedTaxon() {
+ return this.acceptedTaxon;
}
+ protected void setAcceptedTaxon(Taxon acceptedTaxon) {
+ if (acceptedTaxon == null){
+ Taxon oldTaxon = this.acceptedTaxon;
+ this.acceptedTaxon = null;
+ oldTaxon.removeSynonym(this);
+ }else{
+ if (this.acceptedTaxon != null){
+ this.acceptedTaxon.removeSynonym(this, false);
+ }
+ this.acceptedTaxon = acceptedTaxon;
+ this.acceptedTaxon.addSynonym(this);
+ checkHomotypic();
+ }
+ }
+ public SynonymType getType() {
+ return type;
+ }
+ public void setType(SynonymType type) {
+ this.type = type;
+ checkHomotypic();
+ }
+
+//***************** METHODS **************************/
/**
- * Return the synonymy relationship type for the relation to a given accepted taxon.
- * If taxon is null or no relation exists to that taxon null is returned.
- * @param taxon
- * @return
+ * Returns true if this is a synonym of the given taxon.
+ *
+ * @param taxon the taxon to check synonym for
+ * @return true if this is a synonm of the given taxon
+ *
+ * @see #getAcceptedTaxon()
*/
@Transient
- public SynonymRelationshipType getRelationType(Taxon taxon){
- if (taxon == null ){
- return null;
- }
- for (SynonymRelationship rel:getSynonymRelations()){
- Taxon acceptedTaxon = rel.getAcceptedTaxon();
- if (taxon.equals(acceptedTaxon)){
- return rel.getType();
- }
- }
- return null;
+ public boolean isSynonymOf(Taxon taxon){
+ return taxon != null && taxon.equals(this.acceptedTaxon);
+ }
+
+ @Override
+ @Transient
+ public boolean isOrphaned() {
+ return this.acceptedTaxon == null || this.acceptedTaxon.isOrphaned();
+ }
+
+ /**
+ * Checks if the synonym type is homotypic. If it is
+ * the name of this
synonym is added to the {@link HomotypicalGroup
+ * homotypic group} of the {@link Taxon accepted taxon}.
+ */
+ private void checkHomotypic() {
+ if (type != null && type.equals(SynonymType.HOMOTYPIC_SYNONYM_OF)
+ && acceptedTaxon != null && acceptedTaxon.getName() != null){
+ acceptedTaxon.getName().getHomotypicalGroup().addTypifiedName(this.getName());
+ }
+ }
+
+
+
+//*********************** CLONE ********************************************************/
+
+ @Override
+ public Synonym clone() {
+ Synonym result;
+ result = (Synonym)super.clone();
+
+ //no changes to accepted taxon, type, partial, proParte
+
+ return result;
+
}
-}
\ No newline at end of file
+
+
+}