package eu.etaxonomy.cdm.model.name;
-import org.apache.log4j.Logger;
-import org.hibernate.annotations.Cascade;
-import org.hibernate.annotations.CascadeType;
+import java.util.Map;
-import eu.etaxonomy.cdm.model.agent.Agent;
-import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
-import eu.etaxonomy.cdm.strategy.BotanicNameCacheStrategy;
-import eu.etaxonomy.cdm.strategy.TaxonNameParserBotanicalNameImpl;
+import javax.persistence.Entity;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
-import java.util.*;
+import org.apache.log4j.Logger;
+import org.hibernate.envers.Audited;
+import org.hibernate.search.annotations.Indexed;
+import org.springframework.beans.factory.annotation.Configurable;
-import javax.naming.NameParser;
-import javax.persistence.*;
+import eu.etaxonomy.cdm.common.CdmUtils;
+import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
+import eu.etaxonomy.cdm.model.common.CdmBase;
+import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
+import eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy;
+import eu.etaxonomy.cdm.strategy.parser.INonViralNameParser;
+import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
/**
- * Taxon name class for plants
+ * The taxon name class for plants and fungi.
+ * <P>
+ * This class corresponds to: NameBotanical according to the ABCD schema.
+ *
* @author m.doering
* @version 1.0
* @created 08-Nov-2007 13:06:15
*/
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "BotanicalName", propOrder = {
+ "anamorphic"
+})
+@XmlRootElement(name = "BotanicalName")
@Entity
-public class BotanicalName extends NonViralName {
- static Logger logger = Logger.getLogger(BotanicalName.class);
- //if set: this name is a hybrid formula (a hybrid that does not have an own name) and no other hybrid flags may be set. A
- //hybrid name may not have either an authorteam nor other name components.
- private boolean isHybridFormula = false;
- private boolean isMonomHybrid = false;
- private boolean isBinomHybrid = false;
- private boolean isTrinomHybrid = false;
+@Indexed(index = "eu.etaxonomy.cdm.model.name.TaxonNameBase")
+@Audited
+@Configurable
+public class BotanicalName extends NonViralName<BotanicalName> implements Cloneable /*, IMergable*/ {
+ private static final long serialVersionUID = 6818651572463497727L;
+ @SuppressWarnings("unused")
+ private static final Logger logger = Logger.getLogger(BotanicalName.class);
+
//Only for fungi: to indicate that the type of the name is asexual or not
- private boolean isAnamorphic;
- private Set<HybridRelationship> hybridRelationships = new HashSet();
+ @XmlElement(name ="IsAnamorphic")
+ private boolean anamorphic;
- /**
- * @param rank
- * @return
- */
- public static BotanicalName NewInstance(Rank rank){
- return new BotanicalName(rank);
- }
-
- /**
- * Returns a parsed Name
- * @param fullName
- * @return
- */
- public static BotanicalName PARSED_NAME(String fullName){
- return PARSED_NAME(fullName, Rank.GENUS());
- }
-
- /**
- * Returns a parsed Name
- * @param fullName
- * @return
- */
- public static BotanicalName PARSED_NAME(String fullName, Rank rank){
- if (nameParser == null){
- nameParser = new TaxonNameParserBotanicalNameImpl();
- }
- return (BotanicalName)nameParser.parseFullName(fullName, rank);
- }
+ static private INonViralNameParser<?> nameParser = new NonViralNameParserImpl();
+ // ************* CONSTRUCTORS *************/
//needed by hibernate
+ /**
+ * Class constructor: creates a new botanical taxon name instance
+ * only containing the {@link eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy default cache strategy}.
+ *
+ * @see #BotanicalName(Rank, HomotypicalGroup)
+ * @see #BotanicalName(Rank, String, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
+ * @see eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy
+ */
protected BotanicalName(){
super();
- this.cacheStrategy = BotanicNameCacheStrategy.NewInstance();
+ this.cacheStrategy = BotanicNameDefaultCacheStrategy.NewInstance();
}
- public BotanicalName(Rank rank) {
- super(rank);
- this.cacheStrategy = BotanicNameCacheStrategy.NewInstance();
+ /**
+ * Class constructor: creates a new botanical taxon name instance
+ * only containing its {@link Rank rank},
+ * its {@link HomotypicalGroup homotypical group} and
+ * the {@link eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy default cache strategy}.
+ * The new botanical taxon name instance will be also added to the set of
+ * botanical taxon names belonging to this homotypical group.
+ *
+ * @param rank the rank to be assigned to <i>this</i> botanical taxon name
+ * @param homotypicalGroup the homotypical group to which <i>this</i> botanical taxon name belongs
+ * @see #BotanicalName()
+ * @see #BotanicalName(Rank, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
+ * @see eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy
+ */
+ protected BotanicalName(Rank rank, HomotypicalGroup homotypicalGroup) {
+ super(rank, homotypicalGroup);
+ this.cacheStrategy = BotanicNameDefaultCacheStrategy.NewInstance();
}
- public BotanicalName(Rank rank, String genusOrUninomial, String specificEpithet, String infraSpecificEpithet, Agent combinationAuthorTeam, INomenclaturalReference nomenclaturalReference, String nomenclMicroRef) {
- super(rank, genusOrUninomial, specificEpithet, infraSpecificEpithet, combinationAuthorTeam, nomenclaturalReference, nomenclMicroRef);
- this.cacheStrategy = BotanicNameCacheStrategy.NewInstance();
+ /**
+ * Class constructor: creates a new botanical taxon name instance
+ * containing its {@link Rank rank},
+ * its {@link HomotypicalGroup homotypical group},
+ * its scientific name components, its {@link eu.etaxonomy.cdm.model.agent.TeamOrPersonBase author(team)},
+ * its {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference nomenclatural reference} and
+ * the {@link eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy default cache strategy}.
+ * The new botanical taxon name instance will be also added to the set of
+ * botanical taxon names belonging to this homotypical group.
+ *
+ * @param rank the rank to be assigned to <i>this</i> botanical taxon name
+ * @param genusOrUninomial the string for <i>this</i> botanical taxon name
+ * if its rank is genus or higher or for the genus part
+ * if its rank is lower than genus
+ * @param infraGenericEpithet the string for the first epithet of
+ * <i>this</i> botanical taxon name if its rank is lower than genus
+ * and higher than species aggregate
+ * @param specificEpithet the string for the first epithet of
+ * <i>this</i> botanical taxon name if its rank is species aggregate or lower
+ * @param infraSpecificEpithet the string for the second epithet of
+ * <i>this</i> botanical taxon name if its rank is lower than species
+ * @param combinationAuthorTeam the author or the team who published <i>this</i> botanical taxon name
+ * @param nomenclaturalReference the nomenclatural reference where <i>this</i> botanical taxon name was published
+ * @param nomenclMicroRef the string with the details for precise location within the nomenclatural reference
+ * @param homotypicalGroup the homotypical group to which <i>this</i> botanical taxon name belongs
+ * @see #BotanicalName()
+ * @see #BotanicalName(Rank, HomotypicalGroup)
+ * @see #NewInstance(Rank, String, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
+ * @see eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy
+ * @see eu.etaxonomy.cdm.strategy.cache.name.INonViralNameCacheStrategy
+ * @see eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy
+ */
+ protected BotanicalName(Rank rank, String genusOrUninomial, String infraGenericEpithet, String specificEpithet, String infraSpecificEpithet, TeamOrPersonBase combinationAuthorTeam, INomenclaturalReference nomenclaturalReference, String nomenclMicroRef, HomotypicalGroup homotypicalGroup) {
+ super(rank, genusOrUninomial, infraGenericEpithet, specificEpithet, infraSpecificEpithet, combinationAuthorTeam, nomenclaturalReference, nomenclMicroRef, homotypicalGroup);
+ this.cacheStrategy = BotanicNameDefaultCacheStrategy.NewInstance();
}
- @OneToMany
- @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN})
- public Set<HybridRelationship> getHybridRelationships() {
- return hybridRelationships;
- }
- protected void setHybridRelationships(Set<HybridRelationship> relationships) {
- this.hybridRelationships = relationships;
- }
- public void addHybridRelationship(HybridRelationship relationship) {
- this.hybridRelationships.add(relationship);
- }
- public void removeHybridRelationship(HybridRelationship relationship) {
- this.hybridRelationships.remove(relationship);
- }
-
- @Transient
- public Set<HybridRelationship> getParentRelationships() {
- // FIXME: filter relations
- return hybridRelationships;
+ //********* METHODS **************************************/
+
+ /**
+ * Creates a new botanical taxon name instance
+ * only containing its {@link Rank rank} and
+ * the {@link eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy default cache strategy}.
+ *
+ * @param rank the rank to be assigned to <i>this</i> botanical taxon name
+ * @see #BotanicalName(Rank, HomotypicalGroup)
+ * @see #NewInstance(Rank, HomotypicalGroup)
+ * @see #NewInstance(Rank, String, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
+ * @see eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy
+ */
+ public static BotanicalName NewInstance(Rank rank){
+ return new BotanicalName(rank, null);
}
- @Transient
- public Set<HybridRelationship> getChildRelationships() {
- // FIXME: filter relations
- return hybridRelationships;
+ /**
+ * Creates a new botanical taxon name instance
+ * only containing its {@link Rank rank},
+ * its {@link HomotypicalGroup homotypical group} and
+ * the {@link eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy default cache strategy}.
+ * The new botanical taxon name instance will be also added to the set of
+ * botanical taxon names belonging to this homotypical group.
+ *
+ * @param rank the rank to be assigned to <i>this</i> botanical taxon name
+ * @param homotypicalGroup the homotypical group to which <i>this</i> botanical taxon name belongs
+ * @see #NewInstance(Rank)
+ * @see #NewInstance(Rank, String, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
+ * @see #BotanicalName(Rank, HomotypicalGroup)
+ * @see eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy
+ */
+ public static BotanicalName NewInstance(Rank rank, HomotypicalGroup homotypicalGroup){
+ return new BotanicalName(rank, homotypicalGroup);
}
-
-
-
- public boolean isHybridFormula(){
- return this.isHybridFormula;
+ /**
+ * Creates a new botanical taxon name instance
+ * containing its {@link Rank rank},
+ * its {@link HomotypicalGroup homotypical group},
+ * its scientific name components, its {@link eu.etaxonomy.cdm.model.agent.TeamOrPersonBase author(team)},
+ * its {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference nomenclatural reference} and
+ * the {@link eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy default cache strategy}.
+ * The new botanical taxon name instance will be also added to the set of
+ * botanical taxon names belonging to this homotypical group.
+ *
+ * @param rank the rank to be assigned to <i>this</i> botanical taxon name
+ * @param genusOrUninomial the string for <i>this</i> botanical taxon name
+ * if its rank is genus or higher or for the genus part
+ * if its rank is lower than genus
+ * @param infraGenericEpithet the string for the first epithet of
+ * <i>this</i> botanical taxon name if its rank is lower than genus
+ * and higher than species aggregate
+ * @param specificEpithet the string for the first epithet of
+ * <i>this</i> botanical taxon name if its rank is species aggregate or lower
+ * @param infraSpecificEpithet the string for the second epithet of
+ * <i>this</i> botanical taxon name if its rank is lower than species
+ * @param combinationAuthorTeam the author or the team who published <i>this</i> botanical taxon name
+ * @param nomenclaturalReference the nomenclatural reference where <i>this</i> botanical taxon name was published
+ * @param nomenclMicroRef the string with the details for precise location within the nomenclatural reference
+ * @param homotypicalGroup the homotypical group to which <i>this</i> botanical taxon name belongs
+ * @see #NewInstance(Rank)
+ * @see #NewInstance(Rank, HomotypicalGroup)
+ * @see ZoologicalName#ZoologicalName(Rank, String, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
+ * @see eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy
+ */
+ public static BotanicalName NewInstance(Rank rank, String genusOrUninomial, String infraGenericEpithet, String specificEpithet, String infraSpecificEpithet, TeamOrPersonBase combinationAuthorTeam, INomenclaturalReference nomenclaturalReference, String nomenclMicroRef, HomotypicalGroup homotypicalGroup) {
+ return new BotanicalName(rank, genusOrUninomial, infraGenericEpithet, specificEpithet, infraSpecificEpithet, combinationAuthorTeam, nomenclaturalReference, nomenclMicroRef, homotypicalGroup);
}
-
+
/**
+ * Returns a botanical taxon name based on parsing a string representing
+ * all elements (according to the ICBN) of a botanical taxon name (where
+ * the scientific name is an uninomial) including authorship but without
+ * nomenclatural reference. If the {@link Rank rank} is not "Genus" it should be
+ * set afterwards with the {@link TaxonNameBase#setRank(Rank) setRank} methode.
*
- * @param isHybridFormula isHybridFormula
+ * @param fullNameString the string to be parsed
+ * @return the new botanical taxon name
*/
- public void setHybridFormula(boolean isHybridFormula){
- this.isHybridFormula = isHybridFormula;
- }
-
- public boolean isMonomHybrid(){
- return this.isMonomHybrid;
+ public static BotanicalName PARSED_NAME(String fullNameString){
+ return PARSED_NAME(fullNameString, Rank.GENUS());
}
-
+
/**
+ * Returns a botanical taxon name based on parsing a string representing
+ * all elements (according to the ICBN) of a botanical taxon name including
+ * authorship but without nomenclatural reference. The parsing result
+ * depends on the given rank of the botanical taxon name to be created.
*
- * @param isMonomHybrid isMonomHybrid
+ * @param fullNameString the string to be parsed
+ * @param rank the rank of the taxon name
+ * @return the new botanical taxon name
*/
- public void setMonomHybrid(boolean isMonomHybrid){
- this.isMonomHybrid = isMonomHybrid;
+ public static BotanicalName PARSED_NAME(String fullNameString, Rank rank){
+ if (nameParser == null){
+ nameParser = new NonViralNameParserImpl();
+ }
+ return (BotanicalName)nameParser.parseFullName(fullNameString, NomenclaturalCode.ICNAFP, rank);
}
-
- public boolean isBinomHybrid(){
- return this.isBinomHybrid;
+
+ /**
+ * Returns a botanical taxon name based on parsing a string representing
+ * all elements (according to the ICBN) of a botanical taxon name (where
+ * the scientific name is an uninomial) including authorship and
+ * nomenclatural reference. Eventually a new {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference nomenclatural reference}
+ * instance will also be created. If the {@link Rank rank} is not "Genus" it should be
+ * set afterwards with the {@link TaxonNameBase#setRank(Rank) setRank} methode.
+ *
+ * @param fullNameAndReferenceString the string to be parsed
+ * @return the new botanical taxon name
+ */
+ public static BotanicalName PARSED_REFERENCE(String fullNameAndReferenceString){
+ return PARSED_REFERENCE(fullNameAndReferenceString, Rank.GENUS());
}
-
+
/**
+ * Returns a botanical taxon name based on parsing a string representing
+ * all elements (according to the ICBN) of a botanical taxon name including
+ * authorship and nomenclatural reference. The parsing result depends on
+ * the given rank of the botanical taxon name to be created.
+ * Eventually a new {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference nomenclatural reference}
+ * instance will also be created.
*
- * @param isBinomHybrid isBinomHybrid
+ * @param fullNameAndReferenceString the string to be parsed
+ * @param rank the rank of the taxon name
+ * @return the new botanical taxon name
*/
- public void setBinomHybrid(boolean isBinomHybrid){
- this.isBinomHybrid = isBinomHybrid;
+ public static BotanicalName PARSED_REFERENCE(String fullNameAndReferenceString, Rank rank){
+ if (nameParser == null){
+ nameParser = new NonViralNameParserImpl();
+ }
+ return (BotanicalName)nameParser.parseReferencedName(fullNameAndReferenceString, NomenclaturalCode.ICNAFP, rank);
}
- public boolean isTrinomHybrid(){
- return this.isTrinomHybrid;
- }
+//***********************
+ private static Map<String, java.lang.reflect.Field> allFields = null;
+ @Override
+ protected Map<String, java.lang.reflect.Field> getAllFields(){
+ if (allFields == null){
+ allFields = CdmUtils.getAllFields(this.getClass(), CdmBase.class, false, false, false, true);
+ }
+ return allFields;
+ }
+
+//*************************
+
/**
- *
- * @param isTrinomHybrid isTrinomHybrid
+ * Returns the boolean value of the flag indicating whether the specimen
+ * type of <i>this</i> botanical taxon name for a fungus is asexual (true) or not
+ * (false). This applies only in case of fungi. The Article 59 of the ICBN
+ * permits mycologists to give asexually reproducing fungi (anamorphs)
+ * separate names from their sexual states (teleomorphs).
+ *
+ * @return the boolean value of the isAnamorphic flag
*/
- public void setTrinomHybrid(boolean isTrinomHybrid){
- this.isTrinomHybrid = isTrinomHybrid;
+ public boolean isAnamorphic(){
+ return this.anamorphic;
}
- public boolean isAnamorphic(){
- return this.isAnamorphic;
+ /**
+ * @see #isAnamorphic()
+ */
+ public void setAnamorphic(boolean anamorphic){
+ this.anamorphic = anamorphic;
+ }
+
+
+ /**
+ * Returns the {@link NomenclaturalCode nomenclatural code} that governs
+ * the construction of <i>this</i> botanical taxon name, that is the
+ * International Code of Botanical Nomenclature. This method overrides
+ * the getNomeclaturalCode method from {@link NonViralName NonViralName}.
+ *
+ * @return the nomenclatural code for plants
+ * @see NonViralName#isCodeCompliant()
+ * @see TaxonNameBase#getHasProblem()
+ */
+ @Override
+ public NomenclaturalCode getNomenclaturalCode(){
+ return NomenclaturalCode.ICNAFP;
}
+
/**
+ * Checks if this name is an autonym.<BR>
+ * An autonym is a taxon name that has equal specific and infra specific epithets.<BR>
+ * {@link http://ibot.sav.sk/icbn/frameset/0010Ch2Sec1a006.htm#6.8. Vienna Code ยง6.8}
+ * @return true, if name has Rank, Rank is below species and species epithet equals infraSpeciesEpithtet, else false
+ */
+ @Override
+ public boolean isAutonym(){
+ if (this.getRank() != null && this.getSpecificEpithet() != null && this.getInfraSpecificEpithet() != null &&
+ this.getRank().isInfraSpecific() && this.getSpecificEpithet().trim().equals(this.getInfraSpecificEpithet().trim())){
+ return true;
+ }else{
+ return false;
+ }
+ }
+
+//*********************** CLONE ********************************************************/
+
+ /**
+ * Clones <i>this</i> botanical name. This is a shortcut that enables to create
+ * a new instance that differs only slightly from <i>this</i> botanical name by
+ * modifying only some of the attributes.
*
- * @param isAnamorphic isAnamorphic
+ * @see eu.etaxonomy.cdm.model.name.NonViralName#clone()
+ * @see java.lang.Object#clone()
*/
- public void setAnamorphic(boolean isAnamorphic){
- this.isAnamorphic = isAnamorphic;
+ @Override
+ public Object clone() {
+ BotanicalName result = (BotanicalName)super.clone();
+ //no changes to: title, authorTeam, hasProblem, nomenclaturallyRelevant, uri
+ return result;
}
+
}
\ No newline at end of file