675bd95d2f89be652d1f2e0c6e3a470a25c5b126
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / strategy / cache / name / NonViralNameDefaultCacheStrategy.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 package eu.etaxonomy.cdm.strategy.cache.name;
10
11 import java.util.ArrayList;
12 import java.util.Iterator;
13 import java.util.List;
14 import java.util.Set;
15 import java.util.UUID;
16
17 import org.apache.commons.lang.StringUtils;
18 import org.apache.log4j.Logger;
19
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.BotanicalName;
27 import eu.etaxonomy.cdm.model.name.HybridRelationship;
28 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
29 import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
30 import eu.etaxonomy.cdm.model.name.NonViralName;
31 import eu.etaxonomy.cdm.model.name.Rank;
32 import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
33 import eu.etaxonomy.cdm.strategy.TagEnum;
34 import eu.etaxonomy.cdm.strategy.TaggedText;
35 import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
36 import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImplRegExBase;
37
38
39 /**
40 * This class is a default implementation for the INonViralNameCacheStrategy<T extends NonViralName>
41 * interface.<BR>
42 * The method implements a cache strategy for botanical names so no method has to be overwritten by
43 * a subclass for botanic names.
44 * Where differing from this default botanic name strategy other subclasses should overwrite the
45 * existing methods, e.g. a CacheStrategy for zoological names should overwrite getAuthorAndExAuthor
46 * @author a.mueller
47 */
48 /**
49 * @author AM
50 *
51 * @param <T>
52 */
53 public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends NameCacheStrategyBase<T> implements INonViralNameCacheStrategy<T> {
54 private static final Logger logger = Logger.getLogger(NonViralNameDefaultCacheStrategy.class);
55
56 final static UUID uuid = UUID.fromString("1cdda0d1-d5bc-480f-bf08-40a510a2f223");
57
58 protected String NameAuthorSeperator = " ";
59 protected String BasionymStart = "(";
60 protected String BasionymEnd = ")";
61 protected String ExAuthorSeperator = " ex ";
62 protected CharSequence BasionymAuthorCombinationAuthorSeperator = " ";
63
64 @Override
65 public UUID getUuid(){
66 return uuid;
67 }
68
69
70 /**
71 * Factory method
72 * @return NonViralNameDefaultCacheStrategy A new instance of NonViralNameDefaultCacheStrategy
73 */
74 public static NonViralNameDefaultCacheStrategy NewInstance(){
75 return new NonViralNameDefaultCacheStrategy();
76 }
77
78 /**
79 * Factory method
80 * @return NonViralNameDefaultCacheStrategy A new instance of NonViralNameDefaultCacheStrategy
81 */
82 public static <T extends NonViralName<?>> NonViralNameDefaultCacheStrategy<T> NewInstance(Class<T> clazz){
83 return new NonViralNameDefaultCacheStrategy<T>();
84 }
85
86 /**
87 * Constructor
88 */
89 protected NonViralNameDefaultCacheStrategy(){
90 super();
91 }
92
93 /* **************** GETTER / SETTER **************************************/
94
95 /**
96 * String that separates the NameCache part from the AuthorCache part
97 * @return
98 */
99 public String getNameAuthorSeperator() {
100 return NameAuthorSeperator;
101 }
102
103
104 public void setNameAuthorSeperator(String nameAuthorSeperator) {
105 NameAuthorSeperator = nameAuthorSeperator;
106 }
107
108
109 /**
110 * String the basionym author part starts with e.g. '('.
111 * This should correspond with the {@link NonViralNameDefaultCacheStrategy#getBasionymEnd() basionymEnd} attribute
112 * @return
113 */
114 public String getBasionymStart() {
115 return BasionymStart;
116 }
117
118
119 public void setBasionymStart(String basionymStart) {
120 BasionymStart = basionymStart;
121 }
122
123
124 /**
125 * String the basionym author part ends with e.g. ')'.
126 * This should correspond with the {@link NonViralNameDefaultCacheStrategy#getBasionymStart() basionymStart} attribute
127 * @return
128 */
129 public String getBasionymEnd() {
130 return BasionymEnd;
131 }
132
133
134 public void setBasionymEnd(String basionymEnd) {
135 BasionymEnd = basionymEnd;
136 }
137
138
139 /**
140 * String to seperate ex author from author.
141 * @return
142 */
143 public String getExAuthorSeperator() {
144 return ExAuthorSeperator;
145 }
146
147
148 public void setExAuthorSeperator(String exAuthorSeperator) {
149 ExAuthorSeperator = exAuthorSeperator;
150 }
151
152
153 /**
154 * String that seperates the basionym/original_combination author part from the combination author part
155 * @return
156 */
157 public CharSequence getBasionymAuthorCombinationAuthorSeperator() {
158 return BasionymAuthorCombinationAuthorSeperator;
159 }
160
161
162 public void setBasionymAuthorCombinationAuthorSeperator( CharSequence basionymAuthorCombinationAuthorSeperator) {
163 BasionymAuthorCombinationAuthorSeperator = basionymAuthorCombinationAuthorSeperator;
164 }
165
166
167 //** *****************************************************************************************/
168
169 /* (non-Javadoc)
170 * @see eu.etaxonomy.cdm.strategy.cache.name.NameCacheStrategyBase#getTitleCache(eu.etaxonomy.cdm.model.name.TaxonNameBase)
171 */
172 @Override
173 public String getTitleCache(T nonViralName) {
174 List<TaggedText> tags = getTaggedTitle(nonViralName);
175 if (tags == null){
176 return null;
177 }else{
178 String result = createString(tags);
179 return result;
180 }
181 }
182
183 /* (non-Javadoc)
184 * @see eu.etaxonomy.cdm.strategy.cache.name.NameCacheStrategyBase#getFullTitleCache(eu.etaxonomy.cdm.model.name.TaxonNameBase)
185 */
186 @Override
187 public String getFullTitleCache(T nonViralName) {
188 List<TaggedText> tags = getTaggedFullTitle(nonViralName);
189 if (tags == null){
190 return null;
191 }else{
192 String result = createString(tags);
193 return result;
194 }
195 }
196
197
198 /**
199 * Generates and returns the "name cache" (only scientific name without author teams and year).
200 * @see eu.etaxonomy.cdm.strategy.cache.name.INameCacheStrategy#getNameCache(eu.etaxonomy.cdm.model.name.TaxonNameBase)
201 */
202 public String getNameCache(T nonViralName) {
203 List<TaggedText> tags = getTaggedName(nonViralName);
204 if (tags == null){
205 return null;
206 }else{
207 String result = createString(tags);
208 return result;
209 }
210 }
211
212
213 /**
214 * Creates a string from tagged text.
215 * @param tags
216 * @return
217 */
218 protected String createString(List<TaggedText> tags) {
219 StringBuffer result = new StringBuffer();
220
221 boolean isSeparator;
222 boolean wasSeparator = true; //true for start tag
223 for (TaggedText tag: tags){
224 isSeparator = tag.getType().equals(TagEnum.separator);
225 if (! wasSeparator && ! isSeparator ){
226 result.append(" ");
227 }
228 result.append(tag.getText());
229 wasSeparator = isSeparator;
230 }
231 return result.toString();
232 }
233
234 // ******************* Authorship ******************************/
235
236
237 /* (non-Javadoc)
238 * @see eu.etaxonomy.cdm.strategy.cache.INonViralNameCacheStrategy#getAuthorCache(eu.etaxonomy.cdm.model.name.NonViralName)
239 */
240 public String getAuthorshipCache(T nonViralName) {
241 if (nonViralName == null){
242 return null;
243 }
244 //cache protected
245 if (nonViralName.isProtectedAuthorshipCache() == true) {
246 return nonViralName.getAuthorshipCache();
247 }
248 return getNonCacheAuthorshipCache(nonViralName);
249
250 }
251
252 /**
253 * Returns the authorshipcache string for the atomized authorship fields. Does not use the authorshipfield.
254 * @throws NullPointerException if nonViralName is null.
255 * @param nonViralName
256 * @return
257 */
258 protected String getNonCacheAuthorshipCache(T nonViralName){
259 String result = "";
260 INomenclaturalAuthor combinationAuthor = nonViralName.getCombinationAuthorTeam();
261 INomenclaturalAuthor exCombinationAuthor = nonViralName.getExCombinationAuthorTeam();
262 INomenclaturalAuthor basionymAuthor = nonViralName.getBasionymAuthorTeam();
263 INomenclaturalAuthor exBasionymAuthor = nonViralName.getExBasionymAuthorTeam();
264 String basionymPart = "";
265 String authorPart = "";
266 //basionym
267 if (basionymAuthor != null || exBasionymAuthor != null){
268 basionymPart = BasionymStart + getAuthorAndExAuthor(basionymAuthor, exBasionymAuthor) + BasionymEnd;
269 }
270 if (combinationAuthor != null || exCombinationAuthor != null){
271 authorPart = getAuthorAndExAuthor(combinationAuthor, exCombinationAuthor);
272 }
273 result = CdmUtils.concat(BasionymAuthorCombinationAuthorSeperator, basionymPart, authorPart);
274 return result;
275 }
276
277 /**
278 * Returns the AuthorCache part for a combination of an author and an ex author. This applies on combination authors
279 * as well as on basionym/orginal combination authors.
280 * @param author the author
281 * @param exAuthor the ex-author
282 * @return
283 */
284 protected String getAuthorAndExAuthor(INomenclaturalAuthor author, INomenclaturalAuthor exAuthor){
285 String result = "";
286 String authorString = "";
287 String exAuthorString = "";
288 if (author != null){
289 authorString = CdmUtils.Nz(author.getNomenclaturalTitle());
290 }
291 if (exAuthor != null){
292 exAuthorString = CdmUtils.Nz(exAuthor.getNomenclaturalTitle());
293 }
294 if (exAuthorString.length() > 0 ){
295 exAuthorString = exAuthorString + ExAuthorSeperator;
296 }
297 result = exAuthorString + authorString;
298 return result;
299 }
300
301
302 /**
303 * Checks if the given name should include the author in it's cached version.<BR>
304 * This is usually the case but not for <i>species aggregates</i>.
305 * @param nonViralName
306 * @return
307 */
308 protected boolean nameIncludesAuthorship(NonViralName<?> nonViralName){
309 Rank rank = nonViralName.getRank();
310 if (rank != null && rank.isSpeciesAggregate()){
311 return false;
312 }else{
313 return true;
314 }
315 }
316
317 // ************* TAGGED NAME ***************************************/
318
319 /* (non-Javadoc)
320 * @see eu.etaxonomy.cdm.strategy.cache.name.NameCacheStrategyBase#getTaggedFullTitle(eu.etaxonomy.cdm.model.name.TaxonNameBase)
321 */
322 @Override
323 public List<TaggedText> getTaggedFullTitle(T nonViralName) {
324 List<TaggedText> tags = new ArrayList<TaggedText>();
325
326 //null
327 if (nonViralName == null){
328 return null;
329 }
330
331 //protected full title cache
332 if (nonViralName.isProtectedFullTitleCache()){
333 tags.add(new TaggedText(TagEnum.fullName, nonViralName.getFullTitleCache()));
334 return tags;
335 }
336
337 //title cache
338 // String titleCache = nonViralName.getTitleCache();
339 List<TaggedText> titleTags = getTaggedTitle(nonViralName);
340 tags.addAll(titleTags);
341
342
343 //reference
344 String microReference = nonViralName.getNomenclaturalMicroReference();
345 INomenclaturalReference ref = nonViralName.getNomenclaturalReference();
346 String referenceBaseCache = null;
347 if (ref != null){
348 INomenclaturalReference nomenclaturalReference = HibernateProxyHelper.deproxy(ref, INomenclaturalReference.class);
349 nomenclaturalReference.setCacheStrategy(nomenclaturalReference.getType().getCacheStrategy());
350 referenceBaseCache = nomenclaturalReference.getNomenclaturalCitation(microReference);
351 }
352 //add to tags
353 if (StringUtils.isNotBlank(referenceBaseCache)){
354 if (! referenceBaseCache.trim().startsWith("in ")){
355 String refConcat = ", ";
356 tags.add(new TaggedText(TagEnum.separator, refConcat));
357 }
358 tags.add(new TaggedText(TagEnum.reference, referenceBaseCache));
359 }
360
361 //nomenclatural status
362 Set<NomenclaturalStatus> ncStati = nonViralName.getStatus();
363 Iterator<NomenclaturalStatus> iterator = ncStati.iterator();
364 List<TaggedText> nomStatusTags = new ArrayList<TaggedText>();
365 while (iterator.hasNext()) {
366 NomenclaturalStatus ncStatus = (NomenclaturalStatus)iterator.next();
367 // since the NewInstance method of nomencatural status allows null as parameter
368 // we have to check for null values here
369 String suffix = "not defined";
370 if(ncStatus.getType() != null){
371 NomenclaturalStatusType statusType = ncStatus.getType();
372 Language lang = Language.LATIN();
373 Representation repr = statusType.getRepresentation(lang);
374 if (repr != null){
375 suffix = repr.getAbbreviatedLabel();
376 }else{
377 String message = "No latin representation available for nom. status. " + statusType.getTitleCache();
378 logger.warn(message);
379 throw new IllegalStateException(message);
380 }
381 }else if(ncStatus.getRuleConsidered() != null && ! ncStatus.getRuleConsidered().equals("")){
382 suffix = ncStatus.getRuleConsidered();
383 }
384 String statusSeparator = ", ";
385 nomStatusTags.add(new TaggedText(TagEnum.separator, statusSeparator));
386 nomStatusTags.add(new TaggedText(TagEnum.nomStatus, suffix));
387 }
388 tags.addAll(nomStatusTags);
389 return tags;
390
391 }
392
393 /* (non-Javadoc)
394 * @see eu.etaxonomy.cdm.strategy.cache.name.NameCacheStrategyBase#getTaggedTitle(eu.etaxonomy.cdm.model.name.TaxonNameBase)
395 */
396 public List<TaggedText> getTaggedTitle(T nonViralName) {
397 if (nonViralName == null){
398 return null;
399 }
400
401 List<TaggedText> tags = new ArrayList<TaggedText>();
402
403 //TODO how to handle protected fullTitleCache here?
404
405 if (nonViralName.isProtectedTitleCache()){
406 //protected title cache
407 tags.add(new TaggedText(TagEnum.name, nonViralName.getTitleCache()));
408 return tags;
409 }else if (nonViralName.isHybridFormula()){
410 //hybrid formula
411 String hybridSeparator = NonViralNameParserImplRegExBase.hybridSign;
412 boolean isFirst = true;
413 List<HybridRelationship> rels = nonViralName.getOrderedChildRelationships();
414 for (HybridRelationship rel: rels){
415 if (! isFirst){
416 tags.add(new TaggedText(TagEnum.hybridSign, hybridSeparator));
417 }
418 isFirst = false;
419 tags.addAll(getTaggedTitle((T)rel.getParentName()));
420 }
421 return tags;
422 }else if (nonViralName.isAutonym()){
423 //Autonym
424 tags.addAll(handleTaggedAutonym(nonViralName));
425 }else{ //not Autonym
426 // String nameCache = nonViralName.getNameCache(); //OLD: CdmUtils.Nz(getNameCache(nonViralName));
427 List<TaggedText> nameTags = getTaggedName(nonViralName);
428 tags.addAll(nameTags);
429 if (nameIncludesAuthorship(nonViralName)){
430 String authorCache = getAuthorshipCache(nonViralName);
431 if (StringUtils.isNotBlank(authorCache)){
432 tags.add(new TaggedText(TagEnum.authors, authorCache));
433 }
434 }
435 }
436 return tags;
437
438 }
439
440
441 /**
442 * Returns the tag list of the name part (without author and reference).
443 * @param nonViralName
444 * @return
445 */
446 public List<TaggedText> getTaggedName(T nonViralName) {
447 if (nonViralName == null){
448 return null;
449 }
450 List<TaggedText> tags = new ArrayList<TaggedText>();
451 Rank rank = nonViralName.getRank();
452
453 if (nonViralName.isProtectedNameCache()){
454 tags.add(new TaggedText(TagEnum.name, nonViralName.getNameCache()));
455 }else if (rank == null){
456 tags = getRanklessTaggedNameCache(nonViralName);
457 // }else if (nonViralName.isInfragenericUnranked()){
458 // result = getUnrankedInfragenericNameCache(nonViralName);
459 }else if (rank.isInfraSpecific()){
460 tags = getInfraSpeciesTaggedNameCache(nonViralName);
461 }else if (rank.isSpecies()){
462 tags = getSpeciesTaggedNameCache(nonViralName);
463 }else if (rank.isInfraGeneric()){
464 tags = getInfraGenusTaggedNameCache(nonViralName);
465 }else if (rank.isGenus()){
466 tags = getGenusOrUninomialTaggedNameCache(nonViralName);
467 }else if (rank.isSupraGeneric()){
468 tags = getGenusOrUninomialTaggedNameCache(nonViralName);
469 }else{
470 logger.warn("Name Strategy for Name (UUID: " + nonViralName.getUuid() + ") not yet implemented");
471 }
472 //TODO handle appended phrase here instead of different places, check first if this is true for all
473 //cases
474
475 return tags;
476
477 }
478
479
480
481
482 //***************************** PRIVATES ***************************************/
483
484
485 /**
486 * Returns the tag list for an autonym taxon.
487 *
488 * @see NonViralName#isAutonym()
489 * @see BotanicalName#isAutonym()
490 * @param nonViralName
491 * @return
492 */
493 private List<TaggedText> handleTaggedAutonym(T nonViralName) {
494
495 //species part
496 List<TaggedText> tags = getSpeciesTaggedNameCache(nonViralName);
497
498 //author
499 //TODO should this include basionym authors and ex authors
500 INomenclaturalAuthor author = nonViralName.getCombinationAuthorTeam();
501 String authorPart = "";
502 if (author != null){
503 authorPart = CdmUtils.Nz(author.getNomenclaturalTitle());
504 }
505 INomenclaturalAuthor basAuthor = nonViralName.getBasionymAuthorTeam();
506 String basAuthorPart = "";
507 if (basAuthor != null){
508 basAuthorPart = CdmUtils.Nz(basAuthor.getNomenclaturalTitle());
509 }
510 if (! "".equals(basAuthorPart)){
511 authorPart = "("+ basAuthorPart +") " + authorPart;
512 }
513 if (StringUtils.isNotBlank(authorPart)){
514 tags.add(new TaggedText(TagEnum.authors, authorPart));
515 }
516
517
518 //infra species marker
519 if (nonViralName.getRank() == null || !nonViralName.getRank().isInfraSpecific()){
520 //TODO handle exception
521 logger.warn("Rank for autonym does not exist or is not lower than species !!");
522 }else{
523 String infraSpeciesMarker = nonViralName.getRank().getAbbreviation();
524 if (StringUtils.isNotBlank(infraSpeciesMarker)){
525 tags.add(new TaggedText(TagEnum.rank, infraSpeciesMarker));
526 }
527 }
528
529 //infra species
530 String infraSpeciesPart = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet()).trim().replace("null", "");
531 if (StringUtils.isNotBlank(infraSpeciesPart)){
532 tags.add(new TaggedText(TagEnum.name, infraSpeciesPart));
533 }
534
535 return tags;
536 }
537
538
539
540 /**
541 * Returns the tag list for rankless taxa.
542 * @param nonViralName
543 * @return
544 */
545 protected List<TaggedText> getRanklessTaggedNameCache(NonViralName<?> nonViralName){
546 List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
547 String speciesEpi = CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim().replace("null", "");
548 if (StringUtils.isNotBlank(speciesEpi)){
549 tags.add(new TaggedText(TagEnum.name, speciesEpi));
550 }
551
552 String infraSpeciesEpi = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet()).trim().replace("null", "");
553 if (StringUtils.isNotBlank(infraSpeciesEpi)){
554 tags.add(new TaggedText(TagEnum.name, infraSpeciesEpi));
555 }
556
557 //result += " (rankless)";
558 addAppendedTaggedPhrase(tags, nonViralName);
559 return tags;
560 }
561
562 /**
563 * Returns the tag list for the first epithet (including a hybrid sign if required).
564 * @param nonViralName
565 * @return
566 */
567 private List<TaggedText> getUninomialTaggedPart(NonViralName<?> nonViralName) {
568 List<TaggedText> tags = new ArrayList<TaggedText>();
569
570 if (nonViralName.isMonomHybrid()){
571 addHybridPrefix(tags);
572 }
573
574 String uninomial = CdmUtils.Nz(nonViralName.getGenusOrUninomial()).trim().replace("null", "");
575 if (StringUtils.isNotBlank(uninomial)){
576 tags.add(new TaggedText(TagEnum.name, uninomial));
577 }
578
579 return tags;
580 }
581
582 /**
583 * Returns the tag list for an genus or higher taxon.
584 *
585 * @param nonViralName
586 * @return
587 */
588 protected List<TaggedText> getGenusOrUninomialTaggedNameCache(NonViralName<?> nonViralName){
589 List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
590 addAppendedTaggedPhrase(tags, nonViralName);
591 return tags;
592 }
593
594 /**
595 * Returns the tag list for an infrageneric taxon (including species aggregates).
596 *
597 * @see #getSpeciesAggregateTaggedCache(NonViralName)
598 * @param nonViralName
599 * @return
600 */
601 protected List<TaggedText> getInfraGenusTaggedNameCache(NonViralName<?> nonViralName){
602 Rank rank = nonViralName.getRank();
603 if (rank.isSpeciesAggregate()){
604 return getSpeciesAggregateTaggedCache(nonViralName);
605 }
606
607 //genus
608 List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
609
610 //marker
611 String infraGenericMarker = "'unhandled infrageneric rank'";
612 if (rank != null){
613 try {
614 infraGenericMarker = rank.getInfraGenericMarker();
615 } catch (UnknownCdmTypeException e) {
616 infraGenericMarker = "'unhandled infrageneric rank'";
617 }
618 }
619 tags.add(new TaggedText(TagEnum.rank, infraGenericMarker));
620
621
622 String infraGenEpi = CdmUtils.Nz(nonViralName.getInfraGenericEpithet()).trim().replace("null", "");
623 if (StringUtils.isNotBlank(infraGenEpi)){
624 tags.add(new TaggedText(TagEnum.name, infraGenEpi));
625 }
626
627 addAppendedTaggedPhrase(tags, nonViralName);
628 return tags;
629 }
630
631 /**
632 * Returns the tag list for a species aggregate (or similar) taxon.<BR>
633 * Possible ranks for a <i>species aggregate</i> are "aggr.", "species group", ...
634 * @param nonViralName
635 * @return
636 */
637 protected List<TaggedText> getSpeciesAggregateTaggedCache(NonViralName<?> nonViralName){
638 List<TaggedText> tags = getGenusAndSpeciesTaggedPart(nonViralName);
639
640 addSpeciesAggregateTaggedEpithet(tags, nonViralName);
641 addAppendedTaggedPhrase(tags, nonViralName);
642 return tags;
643 }
644
645 /**
646 * Adds the aggregate tag to the tag list.
647 * @param tags
648 * @param nonViralName
649 */
650 private void addSpeciesAggregateTaggedEpithet(List<TaggedText> tags, NonViralName<?> nonViralName) {
651 String marker;
652 try {
653 marker = nonViralName.getRank().getInfraGenericMarker();
654 } catch (UnknownCdmTypeException e) {
655 marker = "'unknown aggregat type'";
656 }
657 if (StringUtils.isNotBlank(marker)){
658 tags.add(new TaggedText(TagEnum.rank, marker));
659 }
660 }
661
662
663 /**
664 * Returns the tag list for a species taxon.
665 * @param nonViralName
666 * @return
667 */
668 protected List<TaggedText> getSpeciesTaggedNameCache(NonViralName<?> nonViralName){
669 List<TaggedText> tags = getGenusAndSpeciesTaggedPart(nonViralName);
670 addAppendedTaggedPhrase(tags, nonViralName);
671 return tags;
672 }
673
674 /**
675 * Creates the tag list for an infraspecific taxon. In include is true the result will contain
676 * @param nonViralName
677 * @return
678 */
679 protected List<TaggedText> getInfraSpeciesTaggedNameCache(NonViralName<?> nonViralName){
680 return getInfraSpeciesTaggedNameCache(nonViralName, true);
681 }
682
683 /**
684 * Creates the tag list for an infraspecific taxon. In include is true the result will contain
685 * the infraspecific marker (e.g. "var.")
686 * @param nonViralName
687 * @param includeMarker
688 * @return
689 */
690 protected List<TaggedText> getInfraSpeciesTaggedNameCache(NonViralName<?> nonViralName, boolean includeMarker){
691 List<TaggedText> tags = getGenusAndSpeciesTaggedPart(nonViralName);
692 if (includeMarker){
693 String marker = (nonViralName.getRank().getAbbreviation()).trim().replace("null", "");
694 if (StringUtils.isNotBlank(marker)){
695 tags.add(new TaggedText(TagEnum.rank, marker));
696 }
697 }
698 String infrSpecEpi = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet());
699 if (nonViralName.isTrinomHybrid()){
700 addHybridPrefix(tags);
701 }
702
703 infrSpecEpi = infrSpecEpi.trim().replace("null", "");
704 if (StringUtils.isNotBlank(infrSpecEpi)){
705 tags.add(new TaggedText(TagEnum.name, infrSpecEpi));
706 }
707
708 addAppendedTaggedPhrase(tags, nonViralName);
709 return tags;
710 }
711
712
713 /**
714 * Adds a tag for the hybrid sign and an empty separator to avoid trailing whitespaces.
715 * @param tags
716 */
717 private void addHybridPrefix(List<TaggedText> tags) {
718 tags.add(new TaggedText(TagEnum.hybridSign, NonViralNameParserImplRegExBase.hybridSign));
719 tags.add(new TaggedText(TagEnum.separator, "")); //no whitespace separator
720 }
721
722 /**
723 * Creates the tag list for the genus and species part.
724 * @param nonViralName
725 * @return
726 */
727 private List<TaggedText> getGenusAndSpeciesTaggedPart(NonViralName<?> nonViralName) {
728 //Uninomial
729 List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
730
731 //InfraGenericEpi
732 boolean hasInfraGenericEpi = StringUtils.isNotBlank(nonViralName.getInfraGenericEpithet());
733 if (hasInfraGenericEpi){
734 String infrGenEpi = nonViralName.getInfraGenericEpithet().trim();
735 if (nonViralName.isBinomHybrid()){
736 // addHybridPrefix(tags); FIXME hybridSign should be tag, but then we need to handle "(" ")" differently.
737 infrGenEpi = NonViralNameParserImplRegExBase.hybridSign + infrGenEpi;
738 }
739 infrGenEpi = "(" + infrGenEpi + ")";
740 tags.add(new TaggedText(TagEnum.name, infrGenEpi));
741 }
742
743 //Species Epi
744 String specEpi = CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim().replace("null", "");
745 if (! hasInfraGenericEpi && nonViralName.isBinomHybrid() ||
746 hasInfraGenericEpi && nonViralName.isTrinomHybrid()){
747 addHybridPrefix(tags);
748 }
749 if (StringUtils.isNotBlank(specEpi)){
750 tags.add(new TaggedText(TagEnum.name, specEpi));
751 }
752 return tags;
753 }
754
755 /**
756 * Adds the tag for the appended phrase if an appended phrase exists
757 * @param tags
758 * @param nonViralName
759 */
760 protected void addAppendedTaggedPhrase(List<TaggedText> tags, NonViralName<?> nonViralName){
761 String appendedPhrase = nonViralName ==null ? null : nonViralName.getAppendedPhrase();
762 if (StringUtils.isNotEmpty(appendedPhrase)){
763 tags.add(new TaggedText(TagEnum.name, appendedPhrase));
764 }
765 }
766
767 public String getLastEpithet(T taxonNameBase) {
768 Rank rank = taxonNameBase.getRank();
769 if(rank.isGenus() || rank.isSupraGeneric()) {
770 return taxonNameBase.getGenusOrUninomial();
771 } else if(rank.isInfraGeneric()) {
772 return taxonNameBase.getInfraGenericEpithet();
773 } else if(rank.isSpecies()) {
774 return taxonNameBase.getSpecificEpithet();
775 } else {
776 return taxonNameBase.getInfraSpecificEpithet();
777 }
778 }
779
780 // *************************** DEPRECATED ***************************************************/
781
782
783 //Old: may be replaced once getTagged(Full)Title is fully tested
784 /* (non-Javadoc)
785 * @see eu.etaxonomy.cdm.strategy.INameCacheStrategy#getTaggedName(eu.etaxonomy.cdm.model.common.CdmBase)
786 */
787 @Override
788 @Deprecated
789 public List<Object> getTaggedNameDeprecated(T nonViralName) {
790 List<Object> tags = new ArrayList<Object>();
791
792 if (nonViralName.isProtectedNameCache() ||
793 nonViralName.isProtectedAuthorshipCache() ||
794 nonViralName.isProtectedFullTitleCache() ||
795 nonViralName.isProtectedTitleCache()){
796 tags.add(nonViralName.getTitleCache());
797 return tags;
798 }
799
800 // Why does it make sense to add the nameCache in case of non existing genusOrUninomial?
801 // if (nonViralName.getGenusOrUninomial() == null){
802 // tags.add(nonViralName.getNameCache());
803 // }else{
804
805 if (nonViralName.getGenusOrUninomial() != null) {
806 tags.add(nonViralName.getGenusOrUninomial());
807 }
808 if (nonViralName.isSpecies() || nonViralName.isInfraSpecific()){
809 tags.add(nonViralName.getSpecificEpithet());
810 }
811
812 // No autonym
813 if (nonViralName.isInfraSpecific() && ! nonViralName.getSpecificEpithet().equals(nonViralName.getInfraSpecificEpithet())){
814 tags.add(nonViralName.getRank());
815 tags.add(nonViralName.getInfraSpecificEpithet());
816 }
817
818 if (nonViralName.isInfraGeneric()){
819 //TODO choose right strategy or generic approach?
820 // --- strategy 1 ---
821
822 if (nonViralName.getRank().isSpeciesAggregate()){
823 tags.add(nonViralName.getSpecificEpithet());
824 tags.add(getSpeciesAggregateEpithet(nonViralName));
825 }else{
826 tags.add(nonViralName.getRank());
827 tags.add(nonViralName.getInfraGenericEpithet());
828 }
829 // --- strategy 2 ---
830 // tags.add('('+nvn.getInfraGenericEpithet()+')');
831 }
832 Team authorTeam = Team.NewInstance();
833 authorTeam.setProtectedTitleCache(true);
834 authorTeam.setTitleCache(nonViralName.getAuthorshipCache(), true);
835 tags.add(authorTeam);
836
837 // Name is an autonym. Rank and infraspecific epitheton follow the author
838 if (nonViralName.isInfraSpecific() && nonViralName.getSpecificEpithet().equals(nonViralName.getInfraSpecificEpithet())){
839 tags.add(nonViralName.getRank());
840 tags.add(nonViralName.getInfraSpecificEpithet());
841 }
842
843 if(! "".equals(nonViralName.getAppendedPhrase())&& (nonViralName.getAppendedPhrase() != null)){
844 tags.add(nonViralName.getAppendedPhrase());
845 }
846
847 return tags;
848 }
849
850
851 /**
852 * @deprecated use only for {@link #getTaggedNameDeprecated(NonViralName)}. Delete when the later
853 * is deleted.
854 */
855 @Deprecated
856 private String getSpeciesAggregateEpithet(NonViralName<?> nonViralName) {
857 String marker;
858 try {
859 marker = nonViralName.getRank().getInfraGenericMarker();
860 } catch (UnknownCdmTypeException e) {
861 marker = "'unknown aggregat type'";
862 }
863 return marker;
864 }
865
866
867 }