2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.cdm
.strategy
.cache
.name
;
11 import java
.util
.ArrayList
;
12 import java
.util
.Iterator
;
13 import java
.util
.List
;
15 import java
.util
.UUID
;
17 import org
.apache
.log4j
.Logger
;
19 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
20 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
21 import eu
.etaxonomy
.cdm
.model
.agent
.INomenclaturalAuthor
;
22 import eu
.etaxonomy
.cdm
.model
.agent
.Team
;
23 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
24 import eu
.etaxonomy
.cdm
.model
.common
.Representation
;
25 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatus
;
26 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatusType
;
27 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
28 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
29 import eu
.etaxonomy
.cdm
.model
.reference
.INomenclaturalReference
;
30 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceBase
;
31 import eu
.etaxonomy
.cdm
.strategy
.exceptions
.UnknownCdmTypeException
;
35 * This class is a default implementation for the INonViralNameCacheStrategy<T extends NonViralName> interface.
36 * The method actually implements a cache strategy for botanical names so no method has to be overwritten by
37 * a subclass for botanic names.
38 * Where differing from this Default BotanicNameCacheStrategy other subclasses should overwrite the existing methods
39 * e.g. a CacheStrategy for zoological names should overwrite getAuthorAndExAuthor
47 public class NonViralNameDefaultCacheStrategy
<T
extends NonViralName
> extends NameCacheStrategyBase
<T
> implements INonViralNameCacheStrategy
<T
> {
48 private static final Logger logger
= Logger
.getLogger(NonViralNameDefaultCacheStrategy
.class);
50 final static UUID uuid
= UUID
.fromString("1cdda0d1-d5bc-480f-bf08-40a510a2f223");
52 protected String NameAuthorSeperator
= " ";
53 protected String BasionymStart
= "(";
54 protected String BasionymEnd
= ")";
55 protected String ExAuthorSeperator
= " ex ";
56 protected CharSequence BasionymAuthorCombinationAuthorSeperator
= " ";
59 public UUID
getUuid(){
66 * @return NonViralNameDefaultCacheStrategy A new instance of NonViralNameDefaultCacheStrategy
68 public static NonViralNameDefaultCacheStrategy
NewInstance(){
69 return new NonViralNameDefaultCacheStrategy();
75 protected NonViralNameDefaultCacheStrategy(){
79 /* **************** GETTER / SETTER **************************************/
82 * String that separates the NameCache part from the AuthorCache part
85 public String
getNameAuthorSeperator() {
86 return NameAuthorSeperator
;
90 public void setNameAuthorSeperator(String nameAuthorSeperator
) {
91 NameAuthorSeperator
= nameAuthorSeperator
;
96 * String the basionym author part starts with e.g. '('.
97 * This should correspond with the {@link NonViralNameDefaultCacheStrategy#getBasionymEnd() basionymEnd} attribute
100 public String
getBasionymStart() {
101 return BasionymStart
;
105 public void setBasionymStart(String basionymStart
) {
106 BasionymStart
= basionymStart
;
111 * String the basionym author part ends with e.g. ')'.
112 * This should correspond with the {@link NonViralNameDefaultCacheStrategy#getBasionymStart() basionymStart} attribute
115 public String
getBasionymEnd() {
120 public void setBasionymEnd(String basionymEnd
) {
121 BasionymEnd
= basionymEnd
;
126 * String to seperate ex author from author.
129 public String
getExAuthorSeperator() {
130 return ExAuthorSeperator
;
134 public void setExAuthorSeperator(String exAuthorSeperator
) {
135 ExAuthorSeperator
= exAuthorSeperator
;
140 * String that seperates the basionym/original_combination author part from the combination author part
143 public CharSequence
getBasionymAuthorCombinationAuthorSeperator() {
144 return BasionymAuthorCombinationAuthorSeperator
;
148 public void setBasionymAuthorCombinationAuthorSeperator(
149 CharSequence basionymAuthorCombinationAuthorSeperator
) {
150 BasionymAuthorCombinationAuthorSeperator
= basionymAuthorCombinationAuthorSeperator
;
154 //** *****************************************************************************************/
158 * @see eu.etaxonomy.cdm.strategy.INameCacheStrategy#getNameCache()
161 public String
getTitleCache(T nonViralName
) {
162 if (nonViralName
== null){
166 if (nonViralName
.isProtectedTitleCache()){
167 return nonViralName
.getTitleCache();
171 if (isAutonym(nonViralName
)){
172 String speciesPart
= getSpeciesNameCache(nonViralName
);
173 //TODO should this include basionym authors and ex authors
174 INomenclaturalAuthor author
= nonViralName
.getCombinationAuthorTeam();
175 String authorPart
= "";
177 authorPart
= CdmUtils
.Nz(author
.getNomenclaturalTitle());
179 INomenclaturalAuthor basAuthor
= nonViralName
.getBasionymAuthorTeam();
180 String basAuthorPart
= "";
181 if (basAuthor
!= null){
182 basAuthorPart
= CdmUtils
.Nz(basAuthor
.getNomenclaturalTitle());
184 if (! "".equals(basAuthorPart
)){
185 authorPart
= "("+ basAuthorPart
+")" + authorPart
;
187 String infraSpeciesPart
= (CdmUtils
.Nz(nonViralName
.getInfraSpecificEpithet()));
189 String infraSpeciesSeparator
= "";
190 if (nonViralName
.getRank() == null || !nonViralName
.getRank().isInfraSpecific()){
191 //TODO handle exception
192 logger
.warn("Rank for autonym does not exist or is not lower than species !!");
194 infraSpeciesSeparator
= nonViralName
.getRank().getAbbreviation();
197 result
= CdmUtils
.concat(" ", new String
[]{speciesPart
, authorPart
, infraSpeciesSeparator
, infraSpeciesPart
});
198 result
= result
.trim().replace("null", "");
200 String nameCache
= nonViralName
.getNameCache(); //OLD: CdmUtils.Nz(getNameCache(nonViralName));
201 if (nameIncludesAuthorship(nonViralName
)){
202 String authorCache
= CdmUtils
.Nz(getAuthorshipCache(nonViralName
));
203 result
= CdmUtils
.concat(NameAuthorSeperator
, nameCache
, authorCache
);
211 protected boolean nameIncludesAuthorship(NonViralName nonViralName
){
212 Rank rank
= nonViralName
.getRank();
213 if (rank
!= null && rank
.isSpeciesAggregate()){
222 public String
getFullTitleCache(T nonViralName
) {
224 if (nonViralName
== null){
228 if (nonViralName
.isProtectedFullTitleCache() == true) {
229 return nonViralName
.getFullTitleCache();
234 String titleCache
= getTitleCache(nonViralName
);
236 String microReference
= nonViralName
.getNomenclaturalMicroReference();
237 ReferenceBase
<?
> ref
= nonViralName
.getNomenclaturalReference();
238 String referenceBaseCache
= null;
240 INomenclaturalReference nomRef
= HibernateProxyHelper
.deproxy(ref
, INomenclaturalReference
.class);
241 referenceBaseCache
= nomRef
.getNomenclaturalCitation(microReference
);
244 //make nomenclatural status
245 String ncStatusCache
= "";
246 Set
<NomenclaturalStatus
> ncStati
= nonViralName
.getStatus();
247 Iterator
<NomenclaturalStatus
> iterator
= ncStati
.iterator();
248 while (iterator
.hasNext()) {
249 NomenclaturalStatus ncStatus
= (NomenclaturalStatus
)iterator
.next();
250 NomenclaturalStatusType statusType
= ncStatus
.getType();
251 Language lang
= Language
.LATIN();
252 Representation repr
= statusType
.getRepresentation(lang
);
253 ncStatusCache
= ", " + repr
.getAbbreviatedLabel();
255 String refConcat
= " ";
256 if (referenceBaseCache
!= null && ! referenceBaseCache
.trim().startsWith("in ")){
259 result
= CdmUtils
.concat(refConcat
, titleCache
, referenceBaseCache
);
260 result
= CdmUtils
.concat("", result
, ncStatusCache
);
266 * Generates and returns the "name cache" (only scientific name without author teams and year).
267 * @see eu.etaxonomy.cdm.strategy.cache.name.INameCacheStrategy#getNameCache(eu.etaxonomy.cdm.model.name.TaxonNameBase)
269 public String
getNameCache(T nonViralName
) {
270 if (nonViralName
== null){
274 Rank rank
= nonViralName
.getRank();
276 if (nonViralName
.isProtectedNameCache()){
277 result
= nonViralName
.getNameCache();
278 }else if (rank
== null){
279 result
= getRanklessNameCache(nonViralName
);
280 }else if (rank
.isInfraSpecific()){
281 result
= getInfraSpeciesNameCache(nonViralName
);
282 }else if (rank
.isSpecies()){
283 result
= getSpeciesNameCache(nonViralName
);
284 }else if (rank
.isInfraGeneric()){
285 result
= getInfraGenusNameCache(nonViralName
);
286 }else if (rank
.isGenus()){
287 result
= getGenusOrUninomialNameCache(nonViralName
);
288 }else if (rank
.isSupraGeneric()){
289 result
= getGenusOrUninomialNameCache(nonViralName
);
291 logger
.warn("Name Strategy for Name (UUID: " + nonViralName
.getUuid() + ") not yet implemented");
299 * @see eu.etaxonomy.cdm.strategy.cache.INonViralNameCacheStrategy#getAuthorCache(eu.etaxonomy.cdm.model.name.NonViralName)
301 public String
getAuthorshipCache(T nonViralName
) {
302 if (nonViralName
== null){
306 if (nonViralName
.isProtectedAuthorshipCache() == true) {
307 return nonViralName
.getAuthorshipCache();
309 return getNonCacheAuthorshipCache(nonViralName
);
314 * Returns the authorshipcache string for the atomized authorship fields. Does not use the authorshipfield.
315 * @throws NullPointerException if nonViralName is null.
316 * @param nonViralName
319 protected String
getNonCacheAuthorshipCache(T nonViralName
){
321 INomenclaturalAuthor combinationAuthor
= nonViralName
.getCombinationAuthorTeam();
322 INomenclaturalAuthor exCombinationAuthor
= nonViralName
.getExCombinationAuthorTeam();
323 INomenclaturalAuthor basionymAuthor
= nonViralName
.getBasionymAuthorTeam();
324 INomenclaturalAuthor exBasionymAuthor
= nonViralName
.getExBasionymAuthorTeam();
325 String basionymPart
= "";
326 String authorPart
= "";
328 if (basionymAuthor
!= null || exBasionymAuthor
!= null){
329 basionymPart
= BasionymStart
+ getAuthorAndExAuthor(basionymAuthor
, exBasionymAuthor
) + BasionymEnd
;
331 if (combinationAuthor
!= null || exCombinationAuthor
!= null){
332 authorPart
= getAuthorAndExAuthor(combinationAuthor
, exCombinationAuthor
);
334 result
= CdmUtils
.concat(BasionymAuthorCombinationAuthorSeperator
, basionymPart
, authorPart
);
339 * Returns the AuthorCache part for a combination of an author and an ex author. This applies on combination authors
340 * as well as on basionym/orginal combination authors.
341 * @param author the author
342 * @param exAuthor the ex-author
345 protected String
getAuthorAndExAuthor(INomenclaturalAuthor author
, INomenclaturalAuthor exAuthor
){
347 String authorString
= "";
348 String exAuthorString
= "";
350 authorString
= CdmUtils
.Nz(author
.getNomenclaturalTitle());
352 if (exAuthor
!= null){
353 exAuthorString
= CdmUtils
.Nz(exAuthor
.getNomenclaturalTitle());
355 if (exAuthorString
.length() > 0 ){
356 exAuthorString
= exAuthorString
+ ExAuthorSeperator
;
358 result
= exAuthorString
+ authorString
;
365 * @see eu.etaxonomy.cdm.strategy.INameCacheStrategy#getTaggedName(eu.etaxonomy.cdm.model.common.CdmBase)
368 public List
<Object
> getTaggedName(T nonViralName
) {
369 List
<Object
> tags
= new ArrayList
<Object
>();
370 tags
.add(nonViralName
.getGenusOrUninomial());
371 if (nonViralName
.isSpecies() || nonViralName
.isInfraSpecific()){
372 tags
.add(nonViralName
.getSpecificEpithet());
376 if (nonViralName
.isInfraSpecific() && ! nonViralName
.getSpecificEpithet().equals(nonViralName
.getInfraSpecificEpithet())){
377 tags
.add(nonViralName
.getRank());
378 tags
.add(nonViralName
.getInfraSpecificEpithet());
381 if (nonViralName
.isInfraGeneric()){
382 //TODO choose right strategy or generic approach?
383 // --- strategy 1 ---
384 tags
.add(nonViralName
.getRank());
385 tags
.add(nonViralName
.getInfraGenericEpithet());
386 // --- strategy 2 ---
387 // tags.add('('+nvn.getInfraGenericEpithet()+')');
389 Team authorTeam
= Team
.NewInstance();
390 authorTeam
.setProtectedTitleCache(true);
391 authorTeam
.setTitleCache(nonViralName
.getAuthorshipCache());
392 tags
.add(authorTeam
);
394 // Name is an autonym. Rank and infraspecific eitheton follow the author
395 if (nonViralName
.isInfraSpecific() && nonViralName
.getSpecificEpithet().equals(nonViralName
.getInfraSpecificEpithet())){
396 tags
.add(nonViralName
.getRank());
397 tags
.add(nonViralName
.getInfraSpecificEpithet());
400 if(! "".equals(nonViralName
.getAppendedPhrase())){
401 tags
.add(nonViralName
.getAppendedPhrase());
408 /************** PRIVATES ****************/
410 protected String
getRanklessNameCache(NonViralName nonViralName
){
412 result
= (result
+ (nonViralName
.getGenusOrUninomial())).trim().replace("null", "");
413 result
+= " " + (CdmUtils
.Nz(nonViralName
.getSpecificEpithet())).trim();
414 result
+= " " + (CdmUtils
.Nz(nonViralName
.getInfraSpecificEpithet())).trim();
415 result
= result
.trim().replace("null", "");
416 //result += " (rankless)";
417 result
= addAppendedPhrase(result
, nonViralName
);
422 protected String
getGenusOrUninomialNameCache(NonViralName nonViralName
){
424 result
= CdmUtils
.Nz(nonViralName
.getGenusOrUninomial());
425 result
= addAppendedPhrase(result
, nonViralName
);
429 protected String
getInfraGenusNameCache(NonViralName nonViralName
){
431 Rank rank
= nonViralName
.getRank();
432 if (rank
.isSpeciesAggregate()){
433 return getSpeciesAggregateCache(nonViralName
);
435 String infraGenericMarker
= "xxx.";
438 infraGenericMarker
= rank
.getInfraGenericMarker();
439 } catch (UnknownCdmTypeException e
) {
440 infraGenericMarker
= "'unhandled infrageneric rank'";
443 result
= CdmUtils
.Nz(nonViralName
.getGenusOrUninomial());
444 result
+= " " + infraGenericMarker
+ " " + (CdmUtils
.Nz(nonViralName
.getInfraGenericEpithet())).trim().replace("null", "");
445 result
= addAppendedPhrase(result
, nonViralName
);
450 protected String
getSpeciesAggregateCache(NonViralName nonViralName
){
452 result
= CdmUtils
.Nz(nonViralName
.getGenusOrUninomial());
453 result
+= " " + CdmUtils
.Nz(nonViralName
.getSpecificEpithet()).trim().replace("null", "");
456 marker
= nonViralName
.getRank().getInfraGenericMarker();
457 } catch (UnknownCdmTypeException e
) {
458 marker
= "'unknown aggregat type'";
460 result
+= " " + marker
;
461 result
= addAppendedPhrase(result
, nonViralName
);
465 protected String
getSpeciesNameCache(NonViralName nonViralName
){
467 result
= CdmUtils
.Nz(nonViralName
.getGenusOrUninomial());
468 result
+= " " + CdmUtils
.Nz(nonViralName
.getSpecificEpithet()).trim().replace("null", "");
469 result
= addAppendedPhrase(result
, nonViralName
);
474 protected String
getInfraSpeciesNameCache(NonViralName nonViralName
){
475 return getInfraSpeciesNameCache(nonViralName
, true);
478 protected String
getInfraSpeciesNameCache(NonViralName nonViralName
, boolean includeMarker
){
480 result
= CdmUtils
.Nz(nonViralName
.getGenusOrUninomial());
481 result
+= " " + (CdmUtils
.Nz(nonViralName
.getSpecificEpithet()).trim()).replace("null", "");
483 result
+= " " + (nonViralName
.getRank().getAbbreviation()).trim().replace("null", "");
485 result
+= " " + (CdmUtils
.Nz(nonViralName
.getInfraSpecificEpithet())).trim().replace("null", "");
486 result
= addAppendedPhrase(result
, nonViralName
);
494 * @return true, if name has Rank, Rank is below species and species epithet equals infraSpeciesEpithtet, else false
496 protected boolean isAutonym(NonViralName nonViralName
){
497 if (nonViralName
!= null && nonViralName
.getRank() != null && nonViralName
.getSpecificEpithet() != null && nonViralName
.getInfraSpecificEpithet() != null &&
498 nonViralName
.getRank().isInfraSpecific() && nonViralName
.getSpecificEpithet().trim().equals(nonViralName
.getInfraSpecificEpithet().trim())){
505 protected String
addAppendedPhrase(String resultString
, NonViralName nonViralName
){
506 String appendedPhrase
= nonViralName
==null ?
null : nonViralName
.getAppendedPhrase();
507 if (resultString
== null){
508 return appendedPhrase
;
509 }else if(appendedPhrase
== null || "".equals(appendedPhrase
.trim())) {
511 }else if ("".equals(resultString
)){
512 return resultString
+ appendedPhrase
;
514 return resultString
+ " " + appendedPhrase
;
519 public String
getLastEpithet(T taxonNameBase
) {
520 Rank rank
= taxonNameBase
.getRank();
521 if(rank
.isGenus() || rank
.isSupraGeneric()) {
522 return taxonNameBase
.getGenusOrUninomial();
523 } else if(rank
.isInfraGeneric()) {
524 return taxonNameBase
.getInfraGenericEpithet();
525 } else if(rank
.isSpecies()) {
526 return taxonNameBase
.getSpecificEpithet();
528 return taxonNameBase
.getInfraSpecificEpithet();