#4114 sort order in taxon navigator and adding that autonyms could be whether infrasp...
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / name / BotanicalName.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.cdm.model.name;
11
12
13 import java.util.Map;
14
15 import javax.persistence.Entity;
16 import javax.xml.bind.annotation.XmlAccessType;
17 import javax.xml.bind.annotation.XmlAccessorType;
18 import javax.xml.bind.annotation.XmlElement;
19 import javax.xml.bind.annotation.XmlRootElement;
20 import javax.xml.bind.annotation.XmlType;
21
22 import org.apache.log4j.Logger;
23 import org.hibernate.envers.Audited;
24 import org.hibernate.search.annotations.Indexed;
25 import org.springframework.beans.factory.annotation.Configurable;
26
27 import eu.etaxonomy.cdm.common.CdmUtils;
28 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
29 import eu.etaxonomy.cdm.model.common.CdmBase;
30 import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
31 import eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy;
32 import eu.etaxonomy.cdm.strategy.parser.INonViralNameParser;
33 import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
34
35 /**
36 * The taxon name class for plants and fungi.
37 * <P>
38 * This class corresponds to: NameBotanical according to the ABCD schema.
39 *
40 * @author m.doering
41 * @version 1.0
42 * @created 08-Nov-2007 13:06:15
43 */
44 @XmlAccessorType(XmlAccessType.FIELD)
45 @XmlType(name = "BotanicalName", propOrder = {
46 "anamorphic"
47 })
48 @XmlRootElement(name = "BotanicalName")
49 @Entity
50 @Indexed(index = "eu.etaxonomy.cdm.model.name.TaxonNameBase")
51 @Audited
52 @Configurable
53 public class BotanicalName extends NonViralName<BotanicalName> implements Cloneable /*, IMergable*/ {
54 private static final long serialVersionUID = 6818651572463497727L;
55 @SuppressWarnings("unused")
56 private static final Logger logger = Logger.getLogger(BotanicalName.class);
57
58 //Only for fungi: to indicate that the type of the name is asexual or not
59 @XmlElement(name ="IsAnamorphic")
60 private boolean anamorphic;
61
62 static private INonViralNameParser<?> nameParser = new NonViralNameParserImpl();
63
64 // ************* CONSTRUCTORS *************/
65 //needed by hibernate
66 /**
67 * Class constructor: creates a new botanical taxon name instance
68 * only containing the {@link eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy default cache strategy}.
69 *
70 * @see #BotanicalName(Rank, HomotypicalGroup)
71 * @see #BotanicalName(Rank, String, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
72 * @see eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy
73 */
74 protected BotanicalName(){
75 super();
76 this.cacheStrategy = BotanicNameDefaultCacheStrategy.NewInstance();
77 }
78 /**
79 * Class constructor: creates a new botanical taxon name instance
80 * only containing its {@link Rank rank},
81 * its {@link HomotypicalGroup homotypical group} and
82 * the {@link eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy default cache strategy}.
83 * The new botanical taxon name instance will be also added to the set of
84 * botanical taxon names belonging to this homotypical group.
85 *
86 * @param rank the rank to be assigned to <i>this</i> botanical taxon name
87 * @param homotypicalGroup the homotypical group to which <i>this</i> botanical taxon name belongs
88 * @see #BotanicalName()
89 * @see #BotanicalName(Rank, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
90 * @see eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy
91 */
92 protected BotanicalName(Rank rank, HomotypicalGroup homotypicalGroup) {
93 super(rank, homotypicalGroup);
94 this.cacheStrategy = BotanicNameDefaultCacheStrategy.NewInstance();
95 }
96 /**
97 * Class constructor: creates a new botanical taxon name instance
98 * containing its {@link Rank rank},
99 * its {@link HomotypicalGroup homotypical group},
100 * its scientific name components, its {@link eu.etaxonomy.cdm.model.agent.TeamOrPersonBase author(team)},
101 * its {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference nomenclatural reference} and
102 * the {@link eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy default cache strategy}.
103 * The new botanical taxon name instance will be also added to the set of
104 * botanical taxon names belonging to this homotypical group.
105 *
106 * @param rank the rank to be assigned to <i>this</i> botanical taxon name
107 * @param genusOrUninomial the string for <i>this</i> botanical taxon name
108 * if its rank is genus or higher or for the genus part
109 * if its rank is lower than genus
110 * @param infraGenericEpithet the string for the first epithet of
111 * <i>this</i> botanical taxon name if its rank is lower than genus
112 * and higher than species aggregate
113 * @param specificEpithet the string for the first epithet of
114 * <i>this</i> botanical taxon name if its rank is species aggregate or lower
115 * @param infraSpecificEpithet the string for the second epithet of
116 * <i>this</i> botanical taxon name if its rank is lower than species
117 * @param combinationAuthorTeam the author or the team who published <i>this</i> botanical taxon name
118 * @param nomenclaturalReference the nomenclatural reference where <i>this</i> botanical taxon name was published
119 * @param nomenclMicroRef the string with the details for precise location within the nomenclatural reference
120 * @param homotypicalGroup the homotypical group to which <i>this</i> botanical taxon name belongs
121 * @see #BotanicalName()
122 * @see #BotanicalName(Rank, HomotypicalGroup)
123 * @see #NewInstance(Rank, String, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
124 * @see eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy
125 * @see eu.etaxonomy.cdm.strategy.cache.name.INonViralNameCacheStrategy
126 * @see eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy
127 */
128 protected BotanicalName(Rank rank, String genusOrUninomial, String infraGenericEpithet, String specificEpithet, String infraSpecificEpithet, TeamOrPersonBase combinationAuthorTeam, INomenclaturalReference nomenclaturalReference, String nomenclMicroRef, HomotypicalGroup homotypicalGroup) {
129 super(rank, genusOrUninomial, infraGenericEpithet, specificEpithet, infraSpecificEpithet, combinationAuthorTeam, nomenclaturalReference, nomenclMicroRef, homotypicalGroup);
130 this.cacheStrategy = BotanicNameDefaultCacheStrategy.NewInstance();
131 }
132
133
134 //********* METHODS **************************************/
135
136 /**
137 * Creates a new botanical taxon name instance
138 * only containing its {@link Rank rank} and
139 * the {@link eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy default cache strategy}.
140 *
141 * @param rank the rank to be assigned to <i>this</i> botanical taxon name
142 * @see #BotanicalName(Rank, HomotypicalGroup)
143 * @see #NewInstance(Rank, HomotypicalGroup)
144 * @see #NewInstance(Rank, String, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
145 * @see eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy
146 */
147 public static BotanicalName NewInstance(Rank rank){
148 return new BotanicalName(rank, null);
149 }
150 /**
151 * Creates a new botanical taxon name instance
152 * only containing its {@link Rank rank},
153 * its {@link HomotypicalGroup homotypical group} and
154 * the {@link eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy default cache strategy}.
155 * The new botanical taxon name instance will be also added to the set of
156 * botanical taxon names belonging to this homotypical group.
157 *
158 * @param rank the rank to be assigned to <i>this</i> botanical taxon name
159 * @param homotypicalGroup the homotypical group to which <i>this</i> botanical taxon name belongs
160 * @see #NewInstance(Rank)
161 * @see #NewInstance(Rank, String, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
162 * @see #BotanicalName(Rank, HomotypicalGroup)
163 * @see eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy
164 */
165 public static BotanicalName NewInstance(Rank rank, HomotypicalGroup homotypicalGroup){
166 return new BotanicalName(rank, homotypicalGroup);
167 }
168 /**
169 * Creates a new botanical taxon name instance
170 * containing its {@link Rank rank},
171 * its {@link HomotypicalGroup homotypical group},
172 * its scientific name components, its {@link eu.etaxonomy.cdm.model.agent.TeamOrPersonBase author(team)},
173 * its {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference nomenclatural reference} and
174 * the {@link eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy default cache strategy}.
175 * The new botanical taxon name instance will be also added to the set of
176 * botanical taxon names belonging to this homotypical group.
177 *
178 * @param rank the rank to be assigned to <i>this</i> botanical taxon name
179 * @param genusOrUninomial the string for <i>this</i> botanical taxon name
180 * if its rank is genus or higher or for the genus part
181 * if its rank is lower than genus
182 * @param infraGenericEpithet the string for the first epithet of
183 * <i>this</i> botanical taxon name if its rank is lower than genus
184 * and higher than species aggregate
185 * @param specificEpithet the string for the first epithet of
186 * <i>this</i> botanical taxon name if its rank is species aggregate or lower
187 * @param infraSpecificEpithet the string for the second epithet of
188 * <i>this</i> botanical taxon name if its rank is lower than species
189 * @param combinationAuthorTeam the author or the team who published <i>this</i> botanical taxon name
190 * @param nomenclaturalReference the nomenclatural reference where <i>this</i> botanical taxon name was published
191 * @param nomenclMicroRef the string with the details for precise location within the nomenclatural reference
192 * @param homotypicalGroup the homotypical group to which <i>this</i> botanical taxon name belongs
193 * @see #NewInstance(Rank)
194 * @see #NewInstance(Rank, HomotypicalGroup)
195 * @see ZoologicalName#ZoologicalName(Rank, String, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
196 * @see eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy
197 */
198 public static BotanicalName NewInstance(Rank rank, String genusOrUninomial, String infraGenericEpithet, String specificEpithet, String infraSpecificEpithet, TeamOrPersonBase combinationAuthorTeam, INomenclaturalReference nomenclaturalReference, String nomenclMicroRef, HomotypicalGroup homotypicalGroup) {
199 return new BotanicalName(rank, genusOrUninomial, infraGenericEpithet, specificEpithet, infraSpecificEpithet, combinationAuthorTeam, nomenclaturalReference, nomenclMicroRef, homotypicalGroup);
200 }
201
202 /**
203 * Returns a botanical taxon name based on parsing a string representing
204 * all elements (according to the ICBN) of a botanical taxon name (where
205 * the scientific name is an uninomial) including authorship but without
206 * nomenclatural reference. If the {@link Rank rank} is not "Genus" it should be
207 * set afterwards with the {@link TaxonNameBase#setRank(Rank) setRank} methode.
208 *
209 * @param fullNameString the string to be parsed
210 * @return the new botanical taxon name
211 */
212 public static BotanicalName PARSED_NAME(String fullNameString){
213 return PARSED_NAME(fullNameString, Rank.GENUS());
214 }
215
216 /**
217 * Returns a botanical taxon name based on parsing a string representing
218 * all elements (according to the ICBN) of a botanical taxon name including
219 * authorship but without nomenclatural reference. The parsing result
220 * depends on the given rank of the botanical taxon name to be created.
221 *
222 * @param fullNameString the string to be parsed
223 * @param rank the rank of the taxon name
224 * @return the new botanical taxon name
225 */
226 public static BotanicalName PARSED_NAME(String fullNameString, Rank rank){
227 if (nameParser == null){
228 nameParser = new NonViralNameParserImpl();
229 }
230 return (BotanicalName)nameParser.parseFullName(fullNameString, NomenclaturalCode.ICNAFP, rank);
231 }
232
233 /**
234 * Returns a botanical taxon name based on parsing a string representing
235 * all elements (according to the ICBN) of a botanical taxon name (where
236 * the scientific name is an uninomial) including authorship and
237 * nomenclatural reference. Eventually a new {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference nomenclatural reference}
238 * instance will also be created. If the {@link Rank rank} is not "Genus" it should be
239 * set afterwards with the {@link TaxonNameBase#setRank(Rank) setRank} methode.
240 *
241 * @param fullNameAndReferenceString the string to be parsed
242 * @return the new botanical taxon name
243 */
244 public static BotanicalName PARSED_REFERENCE(String fullNameAndReferenceString){
245 return PARSED_REFERENCE(fullNameAndReferenceString, Rank.GENUS());
246 }
247
248 /**
249 * Returns a botanical taxon name based on parsing a string representing
250 * all elements (according to the ICBN) of a botanical taxon name including
251 * authorship and nomenclatural reference. The parsing result depends on
252 * the given rank of the botanical taxon name to be created.
253 * Eventually a new {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference nomenclatural reference}
254 * instance will also be created.
255 *
256 * @param fullNameAndReferenceString the string to be parsed
257 * @param rank the rank of the taxon name
258 * @return the new botanical taxon name
259 */
260 public static BotanicalName PARSED_REFERENCE(String fullNameAndReferenceString, Rank rank){
261 if (nameParser == null){
262 nameParser = new NonViralNameParserImpl();
263 }
264 return (BotanicalName)nameParser.parseReferencedName(fullNameAndReferenceString, NomenclaturalCode.ICNAFP, rank);
265 }
266
267 //***********************
268
269 private static Map<String, java.lang.reflect.Field> allFields = null;
270 @Override
271 protected Map<String, java.lang.reflect.Field> getAllFields(){
272 if (allFields == null){
273 allFields = CdmUtils.getAllFields(this.getClass(), CdmBase.class, false, false, false, true);
274 }
275 return allFields;
276 }
277
278 //*************************
279
280 /**
281 * Returns the boolean value of the flag indicating whether the specimen
282 * type of <i>this</i> botanical taxon name for a fungus is asexual (true) or not
283 * (false). This applies only in case of fungi. The Article 59 of the ICBN
284 * permits mycologists to give asexually reproducing fungi (anamorphs)
285 * separate names from their sexual states (teleomorphs).
286 *
287 * @return the boolean value of the isAnamorphic flag
288 */
289 public boolean isAnamorphic(){
290 return this.anamorphic;
291 }
292
293 /**
294 * @see #isAnamorphic()
295 */
296 public void setAnamorphic(boolean anamorphic){
297 this.anamorphic = anamorphic;
298 }
299
300
301 /**
302 * Returns the {@link NomenclaturalCode nomenclatural code} that governs
303 * the construction of <i>this</i> botanical taxon name, that is the
304 * International Code of Botanical Nomenclature. This method overrides
305 * the getNomeclaturalCode method from {@link NonViralName NonViralName}.
306 *
307 * @return the nomenclatural code for plants
308 * @see NonViralName#isCodeCompliant()
309 * @see TaxonNameBase#getHasProblem()
310 */
311 @Override
312 public NomenclaturalCode getNomenclaturalCode(){
313 return NomenclaturalCode.ICNAFP;
314 }
315
316
317 /**
318 * Checks if this name is an autonym.<BR>
319 * An autonym is a taxon name that has equal specific and infra specific epithets.<BR>
320 * {@link http://ibot.sav.sk/icbn/frameset/0010Ch2Sec1a006.htm#6.8. Vienna Code ยง6.8}
321 * or a taxon name that has equal generic and infrageneric epithets (A22.2)
322 * @return true, if name has Rank, Rank is below species and species epithet equals infraSpeciesEpithtet, else false
323 */
324 @Override
325 public boolean isAutonym(){
326 if (this.getRank() != null && this.getSpecificEpithet() != null && this.getInfraSpecificEpithet() != null &&
327 this.getRank().isInfraSpecific() && this.getSpecificEpithet().trim().equals(this.getInfraSpecificEpithet().trim())){
328 return true;
329 }else if (this.getRank() != null && this.getGenusOrUninomial() != null && this.getInfraGenericEpithet() != null &&
330 this.getRank().isInfraGeneric() && this.getGenusOrUninomial().trim().equals(this.getInfraGenericEpithet().trim())){
331 return true;
332 }else{
333 return false;
334 }
335 }
336
337 //*********************** CLONE ********************************************************/
338
339 /**
340 * Clones <i>this</i> botanical name. This is a shortcut that enables to create
341 * a new instance that differs only slightly from <i>this</i> botanical name by
342 * modifying only some of the attributes.
343 *
344 * @see eu.etaxonomy.cdm.model.name.NonViralName#clone()
345 * @see java.lang.Object#clone()
346 */
347 @Override
348 public Object clone() {
349 BotanicalName result = (BotanicalName)super.clone();
350 //no changes to: title, authorTeam, hasProblem, nomenclaturallyRelevant, uri
351 return result;
352 }
353
354
355 }