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
.commons
.lang
.StringUtils
;
18 import org
.apache
.log4j
.Logger
;
20 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
21 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
22 import eu
.etaxonomy
.cdm
.model
.agent
.INomenclaturalAuthor
;
23 import eu
.etaxonomy
.cdm
.model
.agent
.Team
;
24 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
25 import eu
.etaxonomy
.cdm
.model
.common
.Representation
;
26 import eu
.etaxonomy
.cdm
.model
.name
.HybridRelationship
;
27 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatus
;
28 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatusType
;
29 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
30 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
31 import eu
.etaxonomy
.cdm
.model
.reference
.INomenclaturalReference
;
32 import eu
.etaxonomy
.cdm
.strategy
.TagEnum
;
33 import eu
.etaxonomy
.cdm
.strategy
.TaggedText
;
34 import eu
.etaxonomy
.cdm
.strategy
.exceptions
.UnknownCdmTypeException
;
35 import eu
.etaxonomy
.cdm
.strategy
.parser
.NonViralNameParserImplRegExBase
;
39 * This class is a default implementation for the INonViralNameCacheStrategy<T extends NonViralName> interface.
40 * The method actually implements a cache strategy for botanical names so no method has to be overwritten by
41 * a subclass for botanic names.
42 * Where differing from this Default BotanicNameCacheStrategy other subclasses should overwrite the existing methods
43 * e.g. a CacheStrategy for zoological names should overwrite getAuthorAndExAuthor
51 public class NonViralNameDefaultCacheStrategy
<T
extends NonViralName
> extends NameCacheStrategyBase
<T
> implements INonViralNameCacheStrategy
<T
> {
52 private static final Logger logger
= Logger
.getLogger(NonViralNameDefaultCacheStrategy
.class);
54 final static UUID uuid
= UUID
.fromString("1cdda0d1-d5bc-480f-bf08-40a510a2f223");
56 protected String NameAuthorSeperator
= " ";
57 protected String BasionymStart
= "(";
58 protected String BasionymEnd
= ")";
59 protected String ExAuthorSeperator
= " ex ";
60 protected CharSequence BasionymAuthorCombinationAuthorSeperator
= " ";
63 public UUID
getUuid(){
70 * @return NonViralNameDefaultCacheStrategy A new instance of NonViralNameDefaultCacheStrategy
72 public static NonViralNameDefaultCacheStrategy
NewInstance(){
73 return new NonViralNameDefaultCacheStrategy();
78 * @return NonViralNameDefaultCacheStrategy A new instance of NonViralNameDefaultCacheStrategy
80 public static <T
extends NonViralName
<?
>> NonViralNameDefaultCacheStrategy
<T
> NewInstance(Class
<T
> clazz
){
81 return new NonViralNameDefaultCacheStrategy
<T
>();
87 protected NonViralNameDefaultCacheStrategy(){
91 /* **************** GETTER / SETTER **************************************/
94 * String that separates the NameCache part from the AuthorCache part
97 public String
getNameAuthorSeperator() {
98 return NameAuthorSeperator
;
102 public void setNameAuthorSeperator(String nameAuthorSeperator
) {
103 NameAuthorSeperator
= nameAuthorSeperator
;
108 * String the basionym author part starts with e.g. '('.
109 * This should correspond with the {@link NonViralNameDefaultCacheStrategy#getBasionymEnd() basionymEnd} attribute
112 public String
getBasionymStart() {
113 return BasionymStart
;
117 public void setBasionymStart(String basionymStart
) {
118 BasionymStart
= basionymStart
;
123 * String the basionym author part ends with e.g. ')'.
124 * This should correspond with the {@link NonViralNameDefaultCacheStrategy#getBasionymStart() basionymStart} attribute
127 public String
getBasionymEnd() {
132 public void setBasionymEnd(String basionymEnd
) {
133 BasionymEnd
= basionymEnd
;
138 * String to seperate ex author from author.
141 public String
getExAuthorSeperator() {
142 return ExAuthorSeperator
;
146 public void setExAuthorSeperator(String exAuthorSeperator
) {
147 ExAuthorSeperator
= exAuthorSeperator
;
152 * String that seperates the basionym/original_combination author part from the combination author part
155 public CharSequence
getBasionymAuthorCombinationAuthorSeperator() {
156 return BasionymAuthorCombinationAuthorSeperator
;
160 public void setBasionymAuthorCombinationAuthorSeperator(
161 CharSequence basionymAuthorCombinationAuthorSeperator
) {
162 BasionymAuthorCombinationAuthorSeperator
= basionymAuthorCombinationAuthorSeperator
;
166 //** *****************************************************************************************/
169 * @see eu.etaxonomy.cdm.strategy.cache.name.NameCacheStrategyBase#getTitleCache(eu.etaxonomy.cdm.model.name.TaxonNameBase)
172 public String
getTitleCache(T nonViralName
) {
173 List
<TaggedText
> tags
= getTaggedTitle(nonViralName
);
177 String result
= createString(tags
);
184 public String
getTitleCache_OLD(T nonViralName
) {
185 if (nonViralName
== null){
189 if (nonViralName
.isProtectedTitleCache()){
190 return nonViralName
.getTitleCache();
193 if (nonViralName
.isHybridFormula()){
196 String hybridSeparator
= " " + NonViralNameParserImplRegExBase
.hybridSign
+ " ";
197 List
<HybridRelationship
> rels
= nonViralName
.getOrderedChildRelationships();
198 for (HybridRelationship rel
: rels
){
199 result
= CdmUtils
.concat(hybridSeparator
, result
, rel
.getParentName().getTitleCache()).trim();
202 }else if (nonViralName
.isAutonym()){
204 result
= handleAutonym(nonViralName
);
206 String nameCache
= nonViralName
.getNameCache(); //OLD: CdmUtils.Nz(getNameCache(nonViralName));
207 if (nameIncludesAuthorship(nonViralName
)){
208 String authorCache
= CdmUtils
.Nz(getAuthorshipCache(nonViralName
));
209 result
= CdmUtils
.concat(NameAuthorSeperator
, nameCache
, authorCache
);
219 * Creates a string from tagged text.
223 private String
createString(List
<TaggedText
> tags
) {
224 StringBuffer result
= new StringBuffer();
227 boolean wasSeparator
= true; //true for start tag
228 for (TaggedText tag
: tags
){
229 isSeparator
= tag
.getType().equals(TagEnum
.separator
);
230 if (! wasSeparator
&& ! isSeparator
){
233 result
.append(tag
.getText());
234 wasSeparator
= isSeparator
;
236 return result
.toString();
241 * @param nonViralName
245 private List
<TaggedText
> handleTaggedAutonym(T nonViralName
) {
248 List
<TaggedText
> tags
= getSpeciesTaggedNameCache(nonViralName
);
251 //TODO should this include basionym authors and ex authors
252 INomenclaturalAuthor author
= nonViralName
.getCombinationAuthorTeam();
253 String authorPart
= "";
255 authorPart
= CdmUtils
.Nz(author
.getNomenclaturalTitle());
257 INomenclaturalAuthor basAuthor
= nonViralName
.getBasionymAuthorTeam();
258 String basAuthorPart
= "";
259 if (basAuthor
!= null){
260 basAuthorPart
= CdmUtils
.Nz(basAuthor
.getNomenclaturalTitle());
262 if (! "".equals(basAuthorPart
)){
263 authorPart
= "("+ basAuthorPart
+") " + authorPart
;
265 if (StringUtils
.isNotBlank(authorPart
)){
266 tags
.add(new TaggedText(TagEnum
.authors
, authorPart
));
270 //infra species marker
271 if (nonViralName
.getRank() == null || !nonViralName
.getRank().isInfraSpecific()){
272 //TODO handle exception
273 logger
.warn("Rank for autonym does not exist or is not lower than species !!");
275 String infraSpeciesMarker
= nonViralName
.getRank().getAbbreviation();
276 if (StringUtils
.isNotBlank(infraSpeciesMarker
)){
277 tags
.add(new TaggedText(TagEnum
.rank
, infraSpeciesMarker
));
282 String infraSpeciesPart
= CdmUtils
.Nz(nonViralName
.getInfraSpecificEpithet()).trim().replace("null", "");
283 if (StringUtils
.isNotBlank(infraSpeciesPart
)){
284 tags
.add(new TaggedText(TagEnum
.name
, infraSpeciesPart
));
291 * @param nonViralName
295 private String
handleAutonym(T nonViralName
) {
297 String speciesPart
= getSpeciesNameCache(nonViralName
);
298 //TODO should this include basionym authors and ex authors
299 INomenclaturalAuthor author
= nonViralName
.getCombinationAuthorTeam();
300 String authorPart
= "";
302 authorPart
= CdmUtils
.Nz(author
.getNomenclaturalTitle());
304 INomenclaturalAuthor basAuthor
= nonViralName
.getBasionymAuthorTeam();
305 String basAuthorPart
= "";
306 if (basAuthor
!= null){
307 basAuthorPart
= CdmUtils
.Nz(basAuthor
.getNomenclaturalTitle());
309 if (! "".equals(basAuthorPart
)){
310 authorPart
= "("+ basAuthorPart
+") " + authorPart
;
312 String infraSpeciesPart
= (CdmUtils
.Nz(nonViralName
.getInfraSpecificEpithet()));
314 String infraSpeciesSeparator
= "";
315 if (nonViralName
.getRank() == null || !nonViralName
.getRank().isInfraSpecific()){
316 //TODO handle exception
317 logger
.warn("Rank for autonym does not exist or is not lower than species !!");
319 infraSpeciesSeparator
= nonViralName
.getRank().getAbbreviation();
322 result
= CdmUtils
.concat(" ", new String
[]{speciesPart
, authorPart
, infraSpeciesSeparator
, infraSpeciesPart
});
323 result
= result
.trim().replace("null", "");
327 protected boolean nameIncludesAuthorship(NonViralName
<?
> nonViralName
){
328 Rank rank
= nonViralName
.getRank();
329 if (rank
!= null && rank
.isSpeciesAggregate()){
337 * @see eu.etaxonomy.cdm.strategy.cache.name.NameCacheStrategyBase#getFullTitleCache(eu.etaxonomy.cdm.model.name.TaxonNameBase)
340 public String
getFullTitleCache(T nonViralName
) {
341 List
<TaggedText
> tags
= getTaggedFullTitle(nonViralName
);
345 String result
= createString(tags
);
351 public String
getFullTitleCache_OLD(T nonViralName
) {
353 if (nonViralName
== null){
357 if (nonViralName
.isProtectedFullTitleCache() == true) {
358 return nonViralName
.getFullTitleCache();
363 String titleCache
= nonViralName
.getTitleCache(); // OLD: getTitleCache(nonViralName);
365 String microReference
= nonViralName
.getNomenclaturalMicroReference();
366 INomenclaturalReference ref
= nonViralName
.getNomenclaturalReference();
367 String referenceBaseCache
= null;
369 INomenclaturalReference nomenclaturalReference
= HibernateProxyHelper
.deproxy(ref
, INomenclaturalReference
.class);
370 nomenclaturalReference
.setCacheStrategy(nomenclaturalReference
.getType().getCacheStrategy());
371 referenceBaseCache
= nomenclaturalReference
.getNomenclaturalCitation(microReference
);
374 //make nomenclatural status
375 String ncStatusCache
= "";
376 Set
<NomenclaturalStatus
> ncStati
= nonViralName
.getStatus();
377 Iterator
<NomenclaturalStatus
> iterator
= ncStati
.iterator();
378 while (iterator
.hasNext()) {
379 NomenclaturalStatus ncStatus
= (NomenclaturalStatus
)iterator
.next();
380 // since the NewInstance method of nomencatural status allows null as parameter
381 // we have to check for null values here
382 String suffix
= "not defined";
383 if(ncStatus
.getType() != null){
384 NomenclaturalStatusType statusType
= ncStatus
.getType();
385 Language lang
= Language
.LATIN();
386 Representation repr
= statusType
.getRepresentation(lang
);
388 suffix
= repr
.getAbbreviatedLabel();
390 String message
= "No latin representation available for nom. status. " + statusType
.getTitleCache();
391 logger
.warn(message
);
392 throw new IllegalStateException(message
);
394 }else if(ncStatus
.getRuleConsidered() != null && ! ncStatus
.getRuleConsidered().equals("")){
395 suffix
= ncStatus
.getRuleConsidered();
397 ncStatusCache
= ", " + suffix
;
399 String refConcat
= " ";
400 if (referenceBaseCache
!= null && ! referenceBaseCache
.trim().startsWith("in ")){
403 result
= CdmUtils
.concat(refConcat
, titleCache
, referenceBaseCache
);
404 result
= CdmUtils
.concat("", result
, ncStatusCache
);
411 * Generates and returns the "name cache" (only scientific name without author teams and year).
412 * @see eu.etaxonomy.cdm.strategy.cache.name.INameCacheStrategy#getNameCache(eu.etaxonomy.cdm.model.name.TaxonNameBase)
415 public String
getNameCache(T nonViralName
) {
416 List
<TaggedText
> tags
= getNameTags(nonViralName
);
420 String result
= createString(tags
);
425 public String
getNameCache_OLD(T nonViralName
) {
426 if (nonViralName
== null){
430 Rank rank
= nonViralName
.getRank();
432 if (nonViralName
.isProtectedNameCache()){
433 result
= nonViralName
.getNameCache();
434 }else if (rank
== null){
435 result
= getRanklessNameCache(nonViralName
);
436 // }else if (nonViralName.isInfragenericUnranked()){
437 // result = getUnrankedInfragenericNameCache(nonViralName);
438 }else if (rank
.isInfraSpecific()){
439 result
= getInfraSpeciesNameCache(nonViralName
);
440 }else if (rank
.isSpecies()){
441 result
= getSpeciesNameCache(nonViralName
);
442 }else if (rank
.isInfraGeneric()){
443 result
= getInfraGenusNameCache(nonViralName
);
444 }else if (rank
.isGenus()){
445 result
= getGenusOrUninomialNameCache(nonViralName
);
446 }else if (rank
.isSupraGeneric()){
447 result
= getGenusOrUninomialNameCache(nonViralName
);
449 logger
.warn("Name Strategy for Name (UUID: " + nonViralName
.getUuid() + ") not yet implemented");
456 private String
getUnrankedInfragenericNameCache(T nonViralName
) {
458 Rank rank
= nonViralName
.getRank();
459 if (rank
.isSpeciesAggregate()){
460 return getSpeciesAggregateCache(nonViralName
);
462 String infraGenericMarker
= rank
.getAbbreviation();
463 result
= CdmUtils
.Nz(nonViralName
.getGenusOrUninomial()).trim();
464 result
+= " " + infraGenericMarker
+ " " + (CdmUtils
.Nz(nonViralName
.getInfraGenericEpithet())).trim().replace("null", "");
465 result
= addAppendedPhrase(result
, nonViralName
).trim();
471 * @see eu.etaxonomy.cdm.strategy.cache.INonViralNameCacheStrategy#getAuthorCache(eu.etaxonomy.cdm.model.name.NonViralName)
473 public String
getAuthorshipCache(T nonViralName
) {
474 if (nonViralName
== null){
478 if (nonViralName
.isProtectedAuthorshipCache() == true) {
479 return nonViralName
.getAuthorshipCache();
481 return getNonCacheAuthorshipCache(nonViralName
);
486 * Returns the authorshipcache string for the atomized authorship fields. Does not use the authorshipfield.
487 * @throws NullPointerException if nonViralName is null.
488 * @param nonViralName
491 protected String
getNonCacheAuthorshipCache(T nonViralName
){
493 INomenclaturalAuthor combinationAuthor
= nonViralName
.getCombinationAuthorTeam();
494 INomenclaturalAuthor exCombinationAuthor
= nonViralName
.getExCombinationAuthorTeam();
495 INomenclaturalAuthor basionymAuthor
= nonViralName
.getBasionymAuthorTeam();
496 INomenclaturalAuthor exBasionymAuthor
= nonViralName
.getExBasionymAuthorTeam();
497 String basionymPart
= "";
498 String authorPart
= "";
500 if (basionymAuthor
!= null || exBasionymAuthor
!= null){
501 basionymPart
= BasionymStart
+ getAuthorAndExAuthor(basionymAuthor
, exBasionymAuthor
) + BasionymEnd
;
503 if (combinationAuthor
!= null || exCombinationAuthor
!= null){
504 authorPart
= getAuthorAndExAuthor(combinationAuthor
, exCombinationAuthor
);
506 result
= CdmUtils
.concat(BasionymAuthorCombinationAuthorSeperator
, basionymPart
, authorPart
);
511 * Returns the AuthorCache part for a combination of an author and an ex author. This applies on combination authors
512 * as well as on basionym/orginal combination authors.
513 * @param author the author
514 * @param exAuthor the ex-author
517 protected String
getAuthorAndExAuthor(INomenclaturalAuthor author
, INomenclaturalAuthor exAuthor
){
519 String authorString
= "";
520 String exAuthorString
= "";
522 authorString
= CdmUtils
.Nz(author
.getNomenclaturalTitle());
524 if (exAuthor
!= null){
525 exAuthorString
= CdmUtils
.Nz(exAuthor
.getNomenclaturalTitle());
527 if (exAuthorString
.length() > 0 ){
528 exAuthorString
= exAuthorString
+ ExAuthorSeperator
;
530 result
= exAuthorString
+ authorString
;
535 // ************* TAGGED NAME ***************************************/
538 * @see eu.etaxonomy.cdm.strategy.cache.name.NameCacheStrategyBase#getTaggedTitle(eu.etaxonomy.cdm.model.name.TaxonNameBase)
541 public List
<TaggedText
> getTaggedFullTitle(T nonViralName
) {
542 List
<TaggedText
> tags
= new ArrayList
<TaggedText
>();
545 if (nonViralName
== null){
549 //protected full title cache
550 if (nonViralName
.isProtectedFullTitleCache()){
551 tags
.add(new TaggedText(TagEnum
.fullName
, nonViralName
.getFullTitleCache()));
556 // String titleCache = nonViralName.getTitleCache();
557 List
<TaggedText
> titleTags
= getTaggedTitle(nonViralName
);
558 tags
.addAll(titleTags
);
562 String microReference
= nonViralName
.getNomenclaturalMicroReference();
563 INomenclaturalReference ref
= nonViralName
.getNomenclaturalReference();
564 String referenceBaseCache
= null;
566 INomenclaturalReference nomenclaturalReference
= HibernateProxyHelper
.deproxy(ref
, INomenclaturalReference
.class);
567 nomenclaturalReference
.setCacheStrategy(nomenclaturalReference
.getType().getCacheStrategy());
568 referenceBaseCache
= nomenclaturalReference
.getNomenclaturalCitation(microReference
);
571 if (StringUtils
.isNotBlank(referenceBaseCache
)){
572 if (! referenceBaseCache
.trim().startsWith("in ")){
573 String refConcat
= ", ";
574 tags
.add(new TaggedText(TagEnum
.separator
, refConcat
));
576 tags
.add(new TaggedText(TagEnum
.reference
, referenceBaseCache
));
579 //nomenclatural status
580 Set
<NomenclaturalStatus
> ncStati
= nonViralName
.getStatus();
581 Iterator
<NomenclaturalStatus
> iterator
= ncStati
.iterator();
582 List
<TaggedText
> nomStatusTags
= new ArrayList
<TaggedText
>();
583 while (iterator
.hasNext()) {
584 NomenclaturalStatus ncStatus
= (NomenclaturalStatus
)iterator
.next();
585 // since the NewInstance method of nomencatural status allows null as parameter
586 // we have to check for null values here
587 String suffix
= "not defined";
588 if(ncStatus
.getType() != null){
589 NomenclaturalStatusType statusType
= ncStatus
.getType();
590 Language lang
= Language
.LATIN();
591 Representation repr
= statusType
.getRepresentation(lang
);
593 suffix
= repr
.getAbbreviatedLabel();
595 String message
= "No latin representation available for nom. status. " + statusType
.getTitleCache();
596 logger
.warn(message
);
597 throw new IllegalStateException(message
);
599 }else if(ncStatus
.getRuleConsidered() != null && ! ncStatus
.getRuleConsidered().equals("")){
600 suffix
= ncStatus
.getRuleConsidered();
602 String statusSeparator
= ", ";
603 nomStatusTags
.add(new TaggedText(TagEnum
.separator
, statusSeparator
));
604 nomStatusTags
.add(new TaggedText(TagEnum
.nomStatus
, suffix
));
606 tags
.addAll(nomStatusTags
);
611 public List
<TaggedText
> getTaggedTitle(T nonViralName
) {
612 if (nonViralName
== null){
616 List
<TaggedText
> tags
= new ArrayList
<TaggedText
>();
618 //TODO how to handle protected fullTitleCache here?
620 if (nonViralName
.isProtectedTitleCache()){
621 //protected title cache
622 tags
.add(new TaggedText(TagEnum
.name
, nonViralName
.getTitleCache()));
624 }else if (nonViralName
.isHybridFormula()){
626 String hybridSeparator
= NonViralNameParserImplRegExBase
.hybridSign
;
627 boolean isFirst
= true;
628 List
<HybridRelationship
> rels
= nonViralName
.getOrderedChildRelationships();
629 for (HybridRelationship rel
: rels
){
631 tags
.add(new TaggedText(TagEnum
.separator
, hybridSeparator
));
633 tags
.add(new TaggedText(TagEnum
.name
, hybridSeparator
));
635 tags
.addAll(getTaggedTitle((T
)rel
.getParentName()));
638 }else if (nonViralName
.isAutonym()){
640 tags
.addAll(handleTaggedAutonym(nonViralName
));
642 // String nameCache = nonViralName.getNameCache(); //OLD: CdmUtils.Nz(getNameCache(nonViralName));
643 List
<TaggedText
> nameTags
= getNameTags(nonViralName
);
644 tags
.addAll(nameTags
);
645 if (nameIncludesAuthorship(nonViralName
)){
646 String authorCache
= getAuthorshipCache(nonViralName
);
647 if (StringUtils
.isNotBlank(authorCache
)){
648 tags
.add(new TaggedText(TagEnum
.authors
, authorCache
));
658 * @param nonViralName
661 private List
<TaggedText
> getNameTags(T nonViralName
) {
662 if (nonViralName
== null){
665 List
<TaggedText
> tags
= new ArrayList
<TaggedText
>();
666 Rank rank
= nonViralName
.getRank();
668 if (nonViralName
.isProtectedNameCache()){
669 tags
.add(new TaggedText(TagEnum
.name
, nonViralName
.getNameCache()));
670 }else if (rank
== null){
671 tags
= getRanklessTaggedNameCache(nonViralName
);
672 // }else if (nonViralName.isInfragenericUnranked()){
673 // result = getUnrankedInfragenericNameCache(nonViralName);
674 }else if (rank
.isInfraSpecific()){
675 tags
= getInfraSpeciesTaggedNameCache(nonViralName
);
676 }else if (rank
.isSpecies()){
677 tags
= getSpeciesTaggedNameCache(nonViralName
);
678 }else if (rank
.isInfraGeneric()){
679 tags
= getInfraGenusTaggedNameCache(nonViralName
);
680 }else if (rank
.isGenus()){
681 tags
= getGenusOrUninomialTaggedNameCache(nonViralName
);
682 }else if (rank
.isSupraGeneric()){
683 tags
= getGenusOrUninomialTaggedNameCache(nonViralName
);
685 logger
.warn("Name Strategy for Name (UUID: " + nonViralName
.getUuid() + ") not yet implemented");
687 //TODO handle appended phrase here instead of different places, check first if this is true for all
695 //Old: may be replaced once getTagged(Full)Title is fully tested
697 * @see eu.etaxonomy.cdm.strategy.INameCacheStrategy#getTaggedName(eu.etaxonomy.cdm.model.common.CdmBase)
700 public List
<Object
> getTaggedName(T nonViralName
) {
701 List
<Object
> tags
= new ArrayList
<Object
>();
703 if (nonViralName
.isProtectedNameCache() ||
704 nonViralName
.isProtectedAuthorshipCache() ||
705 nonViralName
.isProtectedFullTitleCache() ||
706 nonViralName
.isProtectedTitleCache()){
707 tags
.add(nonViralName
.getTitleCache());
711 // Why does it make sense to add the nameCache in case of non existing genusOrUninomial?
712 // if (nonViralName.getGenusOrUninomial() == null){
713 // tags.add(nonViralName.getNameCache());
716 if (nonViralName
.getGenusOrUninomial() != null) {
717 tags
.add(nonViralName
.getGenusOrUninomial());
719 if (nonViralName
.isSpecies() || nonViralName
.isInfraSpecific()){
720 tags
.add(nonViralName
.getSpecificEpithet());
724 if (nonViralName
.isInfraSpecific() && ! nonViralName
.getSpecificEpithet().equals(nonViralName
.getInfraSpecificEpithet())){
725 tags
.add(nonViralName
.getRank());
726 tags
.add(nonViralName
.getInfraSpecificEpithet());
729 if (nonViralName
.isInfraGeneric()){
730 //TODO choose right strategy or generic approach?
731 // --- strategy 1 ---
733 if (nonViralName
.getRank().isSpeciesAggregate()){
734 tags
.add(nonViralName
.getSpecificEpithet());
735 tags
.add(getSpeciesAggregateEpithet(nonViralName
));
737 tags
.add(nonViralName
.getRank());
738 tags
.add(nonViralName
.getInfraGenericEpithet());
740 // --- strategy 2 ---
741 // tags.add('('+nvn.getInfraGenericEpithet()+')');
743 Team authorTeam
= Team
.NewInstance();
744 authorTeam
.setProtectedTitleCache(true);
745 authorTeam
.setTitleCache(nonViralName
.getAuthorshipCache(), true);
746 tags
.add(authorTeam
);
748 // Name is an autonym. Rank and infraspecific epitheton follow the author
749 if (nonViralName
.isInfraSpecific() && nonViralName
.getSpecificEpithet().equals(nonViralName
.getInfraSpecificEpithet())){
750 tags
.add(nonViralName
.getRank());
751 tags
.add(nonViralName
.getInfraSpecificEpithet());
754 if(! "".equals(nonViralName
.getAppendedPhrase())&& (nonViralName
.getAppendedPhrase() != null)){
755 tags
.add(nonViralName
.getAppendedPhrase());
762 //***************************** PRIVATES ***************************************/
764 protected List
<TaggedText
> getRanklessTaggedNameCache(NonViralName
<?
> nonViralName
){
765 List
<TaggedText
> tags
= getUninomialTaggedPart(nonViralName
);
766 String speciesEpi
= CdmUtils
.Nz(nonViralName
.getSpecificEpithet()).trim().replace("null", "");
767 if (StringUtils
.isNotBlank(speciesEpi
)){
768 tags
.add(new TaggedText(TagEnum
.name
, speciesEpi
));
771 String infraSpeciesEpi
= CdmUtils
.Nz(nonViralName
.getInfraSpecificEpithet()).trim().replace("null", "");
772 if (StringUtils
.isNotBlank(infraSpeciesEpi
)){
773 tags
.add(new TaggedText(TagEnum
.name
, infraSpeciesEpi
));
776 //result += " (rankless)";
777 addAppendedTaggedPhrase(tags
, nonViralName
);
781 protected String
getRanklessNameCache(NonViralName
<?
> nonViralName
){
783 result
= (result
+ (CdmUtils
.Nz(nonViralName
.getGenusOrUninomial()))).trim().replace("null", "");
784 result
+= " " + (CdmUtils
.Nz(nonViralName
.getSpecificEpithet())).trim();
785 result
+= " " + (CdmUtils
.Nz(nonViralName
.getInfraSpecificEpithet())).trim();
786 result
= result
.trim().replace("null", "");
787 //result += " (rankless)";
788 result
= addAppendedPhrase(result
, nonViralName
);
793 protected List
<TaggedText
> getGenusOrUninomialTaggedNameCache(NonViralName
<?
> nonViralName
){
794 List
<TaggedText
> tags
= getUninomialTaggedPart(nonViralName
);
795 addAppendedTaggedPhrase(tags
, nonViralName
);
799 protected String
getGenusOrUninomialNameCache(NonViralName
<?
> nonViralName
){
801 result
= getUninomialPart(nonViralName
);
802 result
= addAppendedPhrase(result
, nonViralName
).trim();
807 private List
<TaggedText
> getUninomialTaggedPart(NonViralName
<?
> nonViralName
) {
808 List
<TaggedText
> tags
= new ArrayList
<TaggedText
>();
810 if (nonViralName
.isMonomHybrid()){
811 addHybridPrefix(tags
);
814 String uninomial
= CdmUtils
.Nz(nonViralName
.getGenusOrUninomial()).trim().replace("null", "");
815 if (StringUtils
.isNotBlank(uninomial
)){
816 tags
.add(new TaggedText(TagEnum
.name
, uninomial
));
822 private String
getUninomialPart(NonViralName
<?
> nonViralName
) {
824 result
= CdmUtils
.Nz(nonViralName
.getGenusOrUninomial()).trim();
825 if (nonViralName
.isMonomHybrid()){
826 result
= NonViralNameParserImplRegExBase
.hybridSign
+ result
;
832 protected List
<TaggedText
> getInfraGenusTaggedNameCache(NonViralName
<?
> nonViralName
){
833 Rank rank
= nonViralName
.getRank();
834 if (rank
.isSpeciesAggregate()){
835 return getSpeciesAggregateTaggedCache(nonViralName
);
839 List
<TaggedText
> tags
= getUninomialTaggedPart(nonViralName
);
842 String infraGenericMarker
= "'unhandled infrageneric rank'";
845 infraGenericMarker
= rank
.getInfraGenericMarker();
846 } catch (UnknownCdmTypeException e
) {
847 infraGenericMarker
= "'unhandled infrageneric rank'";
850 tags
.add(new TaggedText(TagEnum
.rank
, infraGenericMarker
));
853 String infraGenEpi
= CdmUtils
.Nz(nonViralName
.getInfraGenericEpithet()).trim().replace("null", "");
854 if (StringUtils
.isNotBlank(infraGenEpi
)){
855 tags
.add(new TaggedText(TagEnum
.name
, infraGenEpi
));
858 addAppendedTaggedPhrase(tags
, nonViralName
);
862 protected String
getInfraGenusNameCache(NonViralName
<?
> nonViralName
){
864 Rank rank
= nonViralName
.getRank();
865 if (rank
.isSpeciesAggregate()){
866 return getSpeciesAggregateCache(nonViralName
);
868 String infraGenericMarker
= "'unhandled infrageneric rank'";
871 infraGenericMarker
= rank
.getInfraGenericMarker();
872 } catch (UnknownCdmTypeException e
) {
873 infraGenericMarker
= "'unhandled infrageneric rank'";
876 result
= getUninomialPart(nonViralName
);
877 result
+= " " + infraGenericMarker
+ " " + (CdmUtils
.Nz(nonViralName
.getInfraGenericEpithet())).trim().replace("null", "");
878 result
= addAppendedPhrase(result
, nonViralName
).trim();
883 protected List
<TaggedText
> getSpeciesAggregateTaggedCache(NonViralName
<?
> nonViralName
){
884 List
<TaggedText
> tags
= getGenusAndSpeciesTaggedPart(nonViralName
);
886 addSpeciesAggregateTaggedEpithet(tags
, nonViralName
);
887 addAppendedTaggedPhrase(tags
, nonViralName
);
891 private void addSpeciesAggregateTaggedEpithet(List
<TaggedText
> tags
, NonViralName
<?
> nonViralName
) {
894 marker
= nonViralName
.getRank().getInfraGenericMarker();
895 } catch (UnknownCdmTypeException e
) {
896 marker
= "'unknown aggregat type'";
898 if (StringUtils
.isNotBlank(marker
)){
899 tags
.add(new TaggedText(TagEnum
.rank
, marker
));
904 protected String
getSpeciesAggregateCache(NonViralName
<?
> nonViralName
){
905 String result
= getGenusAndSpeciesPart(nonViralName
);
907 result
+= " " + getSpeciesAggregateEpithet(nonViralName
);
908 result
= addAppendedPhrase(result
, nonViralName
).trim();
912 private String
getSpeciesAggregateEpithet(NonViralName
<?
> nonViralName
) {
915 marker
= nonViralName
.getRank().getInfraGenericMarker();
916 } catch (UnknownCdmTypeException e
) {
917 marker
= "'unknown aggregat type'";
923 protected List
<TaggedText
> getSpeciesTaggedNameCache(NonViralName
<?
> nonViralName
){
924 List
<TaggedText
> tags
= getGenusAndSpeciesTaggedPart(nonViralName
);
925 addAppendedTaggedPhrase(tags
, nonViralName
);
929 protected String
getSpeciesNameCache(NonViralName
<?
> nonViralName
){
930 String result
= getGenusAndSpeciesPart(nonViralName
);
931 result
= addAppendedPhrase(result
, nonViralName
).trim();
932 result
= result
.replace("\\s\\", " ");
936 protected List
<TaggedText
> getInfraSpeciesTaggedNameCache(NonViralName
<?
> nonViralName
){
937 return getInfraSpeciesTaggedNameCache(nonViralName
, true);
940 protected List
<TaggedText
> getInfraSpeciesTaggedNameCache(NonViralName
<?
> nonViralName
, boolean includeMarker
){
941 List
<TaggedText
> tags
= getGenusAndSpeciesTaggedPart(nonViralName
);
943 String marker
= (nonViralName
.getRank().getAbbreviation()).trim().replace("null", "");
944 if (StringUtils
.isNotBlank(marker
)){
945 tags
.add(new TaggedText(TagEnum
.rank
, marker
));
948 String infrSpecEpi
= CdmUtils
.Nz(nonViralName
.getInfraSpecificEpithet());
949 if (nonViralName
.isTrinomHybrid()){
950 addHybridPrefix(tags
);
953 infrSpecEpi
= infrSpecEpi
.trim().replace("null", "");
954 if (StringUtils
.isNotBlank(infrSpecEpi
)){
955 tags
.add(new TaggedText(TagEnum
.name
, infrSpecEpi
));
958 addAppendedTaggedPhrase(tags
, nonViralName
);
964 * Adds a tag for the hybrid sign and an empty separator to avoid trailing whitespaces.
967 private void addHybridPrefix(List
<TaggedText
> tags
) {
968 tags
.add(new TaggedText(TagEnum
.hybridSign
, NonViralNameParserImplRegExBase
.hybridSign
));
969 tags
.add(new TaggedText(TagEnum
.separator
, "")); //no whitespace separator
972 protected String
getInfraSpeciesNameCache(NonViralName
<?
> nonViralName
){
973 return getInfraSpeciesNameCache(nonViralName
, true);
977 protected String
getInfraSpeciesNameCache(NonViralName
<?
> nonViralName
, boolean includeMarker
){
978 String result
= getGenusAndSpeciesPart(nonViralName
);
980 result
+= " " + (nonViralName
.getRank().getAbbreviation()).trim().replace("null", "");
982 String infrSpecEpi
= CdmUtils
.Nz(nonViralName
.getInfraSpecificEpithet());
983 if (nonViralName
.isTrinomHybrid()){
984 infrSpecEpi
= NonViralNameParserImplRegExBase
.hybridSign
+ infrSpecEpi
;
986 result
+= " " + (infrSpecEpi
).trim().replace("null", "");
987 result
= addAppendedPhrase(result
, nonViralName
).trim();
992 private List
<TaggedText
> getGenusAndSpeciesTaggedPart(NonViralName
<?
> nonViralName
) {
994 List
<TaggedText
> tags
= getUninomialTaggedPart(nonViralName
);
997 boolean hasInfraGenericEpi
= StringUtils
.isNotBlank(nonViralName
.getInfraGenericEpithet());
998 if (hasInfraGenericEpi
){
999 String infrGenEpi
= nonViralName
.getInfraGenericEpithet().trim();
1000 if (nonViralName
.isBinomHybrid()){
1001 // addHybridPrefix(tags); FIXME hybridSign should be tag, but then we need to handle "(" ")" differently.
1002 infrGenEpi
= NonViralNameParserImplRegExBase
.hybridSign
+ infrGenEpi
;
1004 infrGenEpi
= "(" + infrGenEpi
+ ")";
1005 tags
.add(new TaggedText(TagEnum
.name
, infrGenEpi
));
1009 String specEpi
= CdmUtils
.Nz(nonViralName
.getSpecificEpithet()).trim().replace("null", "");
1010 if (! hasInfraGenericEpi
&& nonViralName
.isBinomHybrid() ||
1011 hasInfraGenericEpi
&& nonViralName
.isTrinomHybrid()){
1012 addHybridPrefix(tags
);
1014 if (StringUtils
.isNotBlank(specEpi
)){
1015 tags
.add(new TaggedText(TagEnum
.name
, specEpi
));
1020 private String
getGenusAndSpeciesPart(NonViralName
<?
> nonViralName
) {
1023 result
= getUninomialPart(nonViralName
);
1026 boolean hasInfraGenericEpi
= StringUtils
.isNotBlank(nonViralName
.getInfraGenericEpithet());
1027 if (hasInfraGenericEpi
){
1028 String infrGenEpi
= nonViralName
.getInfraGenericEpithet().trim();
1029 if (nonViralName
.isBinomHybrid()){
1030 infrGenEpi
= NonViralNameParserImplRegExBase
.hybridSign
+ infrGenEpi
;
1032 result
+= " (" + infrGenEpi
+ ")";
1035 String specEpi
= CdmUtils
.Nz(nonViralName
.getSpecificEpithet()).trim();
1036 if (! hasInfraGenericEpi
&& nonViralName
.isBinomHybrid() ||
1037 hasInfraGenericEpi
&& nonViralName
.isTrinomHybrid()){
1038 specEpi
= NonViralNameParserImplRegExBase
.hybridSign
+ specEpi
;
1040 result
+= " " + (specEpi
).replace("null", "");
1046 * Adds the tag for the appended phrase if an appended phrase exists
1048 * @param nonViralName
1050 protected void addAppendedTaggedPhrase(List
<TaggedText
> tags
, NonViralName
<?
> nonViralName
){
1051 String appendedPhrase
= nonViralName
==null ?
null : nonViralName
.getAppendedPhrase();
1052 if (StringUtils
.isNotEmpty(appendedPhrase
)){
1053 tags
.add(new TaggedText(TagEnum
.name
, appendedPhrase
));
1057 protected String
addAppendedPhrase(String resultString
, NonViralName
<?
> nonViralName
){
1058 String appendedPhrase
= nonViralName
==null ?
null : nonViralName
.getAppendedPhrase();
1059 if (resultString
== null){
1060 return appendedPhrase
;
1061 }else if(appendedPhrase
== null || "".equals(appendedPhrase
.trim())) {
1062 return resultString
;
1063 }else if ("".equals(resultString
)){
1064 return resultString
+ appendedPhrase
;
1066 return resultString
+ " " + appendedPhrase
;
1071 public String
getLastEpithet(T taxonNameBase
) {
1072 Rank rank
= taxonNameBase
.getRank();
1073 if(rank
.isGenus() || rank
.isSupraGeneric()) {
1074 return taxonNameBase
.getGenusOrUninomial();
1075 } else if(rank
.isInfraGeneric()) {
1076 return taxonNameBase
.getInfraGenericEpithet();
1077 } else if(rank
.isSpecies()) {
1078 return taxonNameBase
.getSpecificEpithet();
1080 return taxonNameBase
.getInfraSpecificEpithet();