Refactoring nameCacheStrategy. Use same method for both caches (tagged + string)
[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.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;
36
37
38 /**
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
44 * @author a.mueller
45 */
46 /**
47 * @author AM
48 *
49 * @param <T>
50 */
51 public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends NameCacheStrategyBase<T> implements INonViralNameCacheStrategy<T> {
52 private static final Logger logger = Logger.getLogger(NonViralNameDefaultCacheStrategy.class);
53
54 final static UUID uuid = UUID.fromString("1cdda0d1-d5bc-480f-bf08-40a510a2f223");
55
56 protected String NameAuthorSeperator = " ";
57 protected String BasionymStart = "(";
58 protected String BasionymEnd = ")";
59 protected String ExAuthorSeperator = " ex ";
60 protected CharSequence BasionymAuthorCombinationAuthorSeperator = " ";
61
62 @Override
63 public UUID getUuid(){
64 return uuid;
65 }
66
67
68 /**
69 * Factory method
70 * @return NonViralNameDefaultCacheStrategy A new instance of NonViralNameDefaultCacheStrategy
71 */
72 public static NonViralNameDefaultCacheStrategy NewInstance(){
73 return new NonViralNameDefaultCacheStrategy();
74 }
75
76 /**
77 * Factory method
78 * @return NonViralNameDefaultCacheStrategy A new instance of NonViralNameDefaultCacheStrategy
79 */
80 public static <T extends NonViralName<?>> NonViralNameDefaultCacheStrategy<T> NewInstance(Class<T> clazz){
81 return new NonViralNameDefaultCacheStrategy<T>();
82 }
83
84 /**
85 * Constructor
86 */
87 protected NonViralNameDefaultCacheStrategy(){
88 super();
89 }
90
91 /* **************** GETTER / SETTER **************************************/
92
93 /**
94 * String that separates the NameCache part from the AuthorCache part
95 * @return
96 */
97 public String getNameAuthorSeperator() {
98 return NameAuthorSeperator;
99 }
100
101
102 public void setNameAuthorSeperator(String nameAuthorSeperator) {
103 NameAuthorSeperator = nameAuthorSeperator;
104 }
105
106
107 /**
108 * String the basionym author part starts with e.g. '('.
109 * This should correspond with the {@link NonViralNameDefaultCacheStrategy#getBasionymEnd() basionymEnd} attribute
110 * @return
111 */
112 public String getBasionymStart() {
113 return BasionymStart;
114 }
115
116
117 public void setBasionymStart(String basionymStart) {
118 BasionymStart = basionymStart;
119 }
120
121
122 /**
123 * String the basionym author part ends with e.g. ')'.
124 * This should correspond with the {@link NonViralNameDefaultCacheStrategy#getBasionymStart() basionymStart} attribute
125 * @return
126 */
127 public String getBasionymEnd() {
128 return BasionymEnd;
129 }
130
131
132 public void setBasionymEnd(String basionymEnd) {
133 BasionymEnd = basionymEnd;
134 }
135
136
137 /**
138 * String to seperate ex author from author.
139 * @return
140 */
141 public String getExAuthorSeperator() {
142 return ExAuthorSeperator;
143 }
144
145
146 public void setExAuthorSeperator(String exAuthorSeperator) {
147 ExAuthorSeperator = exAuthorSeperator;
148 }
149
150
151 /**
152 * String that seperates the basionym/original_combination author part from the combination author part
153 * @return
154 */
155 public CharSequence getBasionymAuthorCombinationAuthorSeperator() {
156 return BasionymAuthorCombinationAuthorSeperator;
157 }
158
159
160 public void setBasionymAuthorCombinationAuthorSeperator(
161 CharSequence basionymAuthorCombinationAuthorSeperator) {
162 BasionymAuthorCombinationAuthorSeperator = basionymAuthorCombinationAuthorSeperator;
163 }
164
165
166 //** *****************************************************************************************/
167
168 /* (non-Javadoc)
169 * @see eu.etaxonomy.cdm.strategy.cache.name.NameCacheStrategyBase#getTitleCache(eu.etaxonomy.cdm.model.name.TaxonNameBase)
170 */
171 @Override
172 public String getTitleCache(T nonViralName) {
173 List<TaggedText> tags = getTaggedTitle(nonViralName);
174 if (tags == null){
175 return null;
176 }else{
177 String result = createString(tags);
178 return result;
179 }
180 }
181
182
183
184 public String getTitleCache_OLD(T nonViralName) {
185 if (nonViralName == null){
186 return null;
187 }
188
189 if (nonViralName.isProtectedTitleCache()){
190 return nonViralName.getTitleCache();
191 }
192 String result = "";
193 if (nonViralName.isHybridFormula()){
194 //hybrid formula
195 result = null;
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();
200 }
201 return result;
202 }else if (nonViralName.isAutonym()){
203 //Autonym
204 result = handleAutonym(nonViralName);
205 }else{ //not Autonym
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);
210 }else{
211 result = nameCache;
212 }
213 }
214 return result;
215 }
216
217
218 /**
219 * Creates a string from tagged text.
220 * @param tags
221 * @return
222 */
223 private String createString(List<TaggedText> tags) {
224 StringBuffer result = new StringBuffer();
225
226 boolean isSeparator;
227 boolean wasSeparator = true; //true for start tag
228 for (TaggedText tag: tags){
229 isSeparator = tag.getType().equals(TagEnum.separator);
230 if (! wasSeparator && ! isSeparator ){
231 result.append(" ");
232 }
233 result.append(tag.getText());
234 wasSeparator = isSeparator;
235 }
236 return result.toString();
237 }
238
239
240 /**
241 * @param nonViralName
242 * @param speciesPart
243 * @return
244 */
245 private List<TaggedText> handleTaggedAutonym(T nonViralName) {
246
247 //species part
248 List<TaggedText> tags = getSpeciesTaggedNameCache(nonViralName);
249
250 //author
251 //TODO should this include basionym authors and ex authors
252 INomenclaturalAuthor author = nonViralName.getCombinationAuthorTeam();
253 String authorPart = "";
254 if (author != null){
255 authorPart = CdmUtils.Nz(author.getNomenclaturalTitle());
256 }
257 INomenclaturalAuthor basAuthor = nonViralName.getBasionymAuthorTeam();
258 String basAuthorPart = "";
259 if (basAuthor != null){
260 basAuthorPart = CdmUtils.Nz(basAuthor.getNomenclaturalTitle());
261 }
262 if (! "".equals(basAuthorPart)){
263 authorPart = "("+ basAuthorPart +") " + authorPart;
264 }
265 if (StringUtils.isNotBlank(authorPart)){
266 tags.add(new TaggedText(TagEnum.authors, authorPart));
267 }
268
269
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 !!");
274 }else{
275 String infraSpeciesMarker = nonViralName.getRank().getAbbreviation();
276 if (StringUtils.isNotBlank(infraSpeciesMarker)){
277 tags.add(new TaggedText(TagEnum.rank, infraSpeciesMarker));
278 }
279 }
280
281 //infra species
282 String infraSpeciesPart = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet()).trim().replace("null", "");
283 if (StringUtils.isNotBlank(infraSpeciesPart)){
284 tags.add(new TaggedText(TagEnum.name, infraSpeciesPart));
285 }
286
287 return tags;
288 }
289
290 /**
291 * @param nonViralName
292 * @param speciesPart
293 * @return
294 */
295 private String handleAutonym(T nonViralName) {
296 String result;
297 String speciesPart = getSpeciesNameCache(nonViralName);
298 //TODO should this include basionym authors and ex authors
299 INomenclaturalAuthor author = nonViralName.getCombinationAuthorTeam();
300 String authorPart = "";
301 if (author != null){
302 authorPart = CdmUtils.Nz(author.getNomenclaturalTitle());
303 }
304 INomenclaturalAuthor basAuthor = nonViralName.getBasionymAuthorTeam();
305 String basAuthorPart = "";
306 if (basAuthor != null){
307 basAuthorPart = CdmUtils.Nz(basAuthor.getNomenclaturalTitle());
308 }
309 if (! "".equals(basAuthorPart)){
310 authorPart = "("+ basAuthorPart +") " + authorPart;
311 }
312 String infraSpeciesPart = (CdmUtils.Nz(nonViralName.getInfraSpecificEpithet()));
313
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 !!");
318 }else{
319 infraSpeciesSeparator = nonViralName.getRank().getAbbreviation();
320 }
321
322 result = CdmUtils.concat(" ", new String[]{speciesPart, authorPart, infraSpeciesSeparator, infraSpeciesPart});
323 result = result.trim().replace("null", "");
324 return result;
325 }
326
327 protected boolean nameIncludesAuthorship(NonViralName<?> nonViralName){
328 Rank rank = nonViralName.getRank();
329 if (rank != null && rank.isSpeciesAggregate()){
330 return false;
331 }else{
332 return true;
333 }
334 }
335
336 /* (non-Javadoc)
337 * @see eu.etaxonomy.cdm.strategy.cache.name.NameCacheStrategyBase#getFullTitleCache(eu.etaxonomy.cdm.model.name.TaxonNameBase)
338 */
339 @Override
340 public String getFullTitleCache(T nonViralName) {
341 List<TaggedText> tags = getTaggedFullTitle(nonViralName);
342 if (tags == null){
343 return null;
344 }else{
345 String result = createString(tags);
346 return result;
347 }
348 }
349
350
351 public String getFullTitleCache_OLD(T nonViralName) {
352 //null
353 if (nonViralName == null){
354 return null;
355 }
356 //full title cache
357 if (nonViralName.isProtectedFullTitleCache() == true) {
358 return nonViralName.getFullTitleCache();
359 }
360
361 String result = "";
362 //title cache
363 String titleCache = nonViralName.getTitleCache(); // OLD: getTitleCache(nonViralName);
364
365 String microReference = nonViralName.getNomenclaturalMicroReference();
366 INomenclaturalReference ref = nonViralName.getNomenclaturalReference();
367 String referenceBaseCache = null;
368 if (ref != null){
369 INomenclaturalReference nomenclaturalReference = HibernateProxyHelper.deproxy(ref, INomenclaturalReference.class);
370 nomenclaturalReference.setCacheStrategy(nomenclaturalReference.getType().getCacheStrategy());
371 referenceBaseCache = nomenclaturalReference.getNomenclaturalCitation(microReference);
372 }
373
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);
387 if (repr != null){
388 suffix = repr.getAbbreviatedLabel();
389 }else{
390 String message = "No latin representation available for nom. status. " + statusType.getTitleCache();
391 logger.warn(message);
392 throw new IllegalStateException(message);
393 }
394 }else if(ncStatus.getRuleConsidered() != null && ! ncStatus.getRuleConsidered().equals("")){
395 suffix = ncStatus.getRuleConsidered();
396 }
397 ncStatusCache = ", " + suffix;
398 }
399 String refConcat = " ";
400 if (referenceBaseCache != null && ! referenceBaseCache.trim().startsWith("in ")){
401 refConcat = ", ";
402 }
403 result = CdmUtils.concat(refConcat, titleCache, referenceBaseCache);
404 result = CdmUtils.concat("", result, ncStatusCache);
405 return result;
406 }
407
408
409
410 /**
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)
413 */
414 @Override
415 public String getNameCache(T nonViralName) {
416 List<TaggedText> tags = getNameTags(nonViralName);
417 if (tags == null){
418 return null;
419 }else{
420 String result = createString(tags);
421 return result;
422 }
423 }
424
425 public String getNameCache_OLD(T nonViralName) {
426 if (nonViralName == null){
427 return null;
428 }
429 String result;
430 Rank rank = nonViralName.getRank();
431
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);
448 }else{
449 logger.warn("Name Strategy for Name (UUID: " + nonViralName.getUuid() + ") not yet implemented");
450 result = "";
451 }
452 return result;
453 }
454
455
456 private String getUnrankedInfragenericNameCache(T nonViralName) {
457 String result;
458 Rank rank = nonViralName.getRank();
459 if (rank.isSpeciesAggregate()){
460 return getSpeciesAggregateCache(nonViralName);
461 }
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();
466 return result;
467 }
468
469
470 /* (non-Javadoc)
471 * @see eu.etaxonomy.cdm.strategy.cache.INonViralNameCacheStrategy#getAuthorCache(eu.etaxonomy.cdm.model.name.NonViralName)
472 */
473 public String getAuthorshipCache(T nonViralName) {
474 if (nonViralName == null){
475 return null;
476 }
477 //cache protected
478 if (nonViralName.isProtectedAuthorshipCache() == true) {
479 return nonViralName.getAuthorshipCache();
480 }
481 return getNonCacheAuthorshipCache(nonViralName);
482
483 }
484
485 /**
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
489 * @return
490 */
491 protected String getNonCacheAuthorshipCache(T nonViralName){
492 String result = "";
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 = "";
499 //basionym
500 if (basionymAuthor != null || exBasionymAuthor != null){
501 basionymPart = BasionymStart + getAuthorAndExAuthor(basionymAuthor, exBasionymAuthor) + BasionymEnd;
502 }
503 if (combinationAuthor != null || exCombinationAuthor != null){
504 authorPart = getAuthorAndExAuthor(combinationAuthor, exCombinationAuthor);
505 }
506 result = CdmUtils.concat(BasionymAuthorCombinationAuthorSeperator, basionymPart, authorPart);
507 return result;
508 }
509
510 /**
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
515 * @return
516 */
517 protected String getAuthorAndExAuthor(INomenclaturalAuthor author, INomenclaturalAuthor exAuthor){
518 String result = "";
519 String authorString = "";
520 String exAuthorString = "";
521 if (author != null){
522 authorString = CdmUtils.Nz(author.getNomenclaturalTitle());
523 }
524 if (exAuthor != null){
525 exAuthorString = CdmUtils.Nz(exAuthor.getNomenclaturalTitle());
526 }
527 if (exAuthorString.length() > 0 ){
528 exAuthorString = exAuthorString + ExAuthorSeperator;
529 }
530 result = exAuthorString + authorString;
531 return result;
532
533 }
534
535 // ************* TAGGED NAME ***************************************/
536
537 /* (non-Javadoc)
538 * @see eu.etaxonomy.cdm.strategy.cache.name.NameCacheStrategyBase#getTaggedTitle(eu.etaxonomy.cdm.model.name.TaxonNameBase)
539 */
540 @Override
541 public List<TaggedText> getTaggedFullTitle(T nonViralName) {
542 List<TaggedText> tags = new ArrayList<TaggedText>();
543
544 //null
545 if (nonViralName == null){
546 return null;
547 }
548
549 //protected full title cache
550 if (nonViralName.isProtectedFullTitleCache()){
551 tags.add(new TaggedText(TagEnum.fullName, nonViralName.getFullTitleCache()));
552 return tags;
553 }
554
555 //title cache
556 // String titleCache = nonViralName.getTitleCache();
557 List<TaggedText> titleTags = getTaggedTitle(nonViralName);
558 tags.addAll(titleTags);
559
560
561 //reference
562 String microReference = nonViralName.getNomenclaturalMicroReference();
563 INomenclaturalReference ref = nonViralName.getNomenclaturalReference();
564 String referenceBaseCache = null;
565 if (ref != null){
566 INomenclaturalReference nomenclaturalReference = HibernateProxyHelper.deproxy(ref, INomenclaturalReference.class);
567 nomenclaturalReference.setCacheStrategy(nomenclaturalReference.getType().getCacheStrategy());
568 referenceBaseCache = nomenclaturalReference.getNomenclaturalCitation(microReference);
569 }
570 //add to tags
571 if (StringUtils.isNotBlank(referenceBaseCache)){
572 if (! referenceBaseCache.trim().startsWith("in ")){
573 String refConcat = ", ";
574 tags.add(new TaggedText(TagEnum.separator, refConcat));
575 }
576 tags.add(new TaggedText(TagEnum.reference, referenceBaseCache));
577 }
578
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);
592 if (repr != null){
593 suffix = repr.getAbbreviatedLabel();
594 }else{
595 String message = "No latin representation available for nom. status. " + statusType.getTitleCache();
596 logger.warn(message);
597 throw new IllegalStateException(message);
598 }
599 }else if(ncStatus.getRuleConsidered() != null && ! ncStatus.getRuleConsidered().equals("")){
600 suffix = ncStatus.getRuleConsidered();
601 }
602 String statusSeparator = ", ";
603 nomStatusTags.add(new TaggedText(TagEnum.separator, statusSeparator));
604 nomStatusTags.add(new TaggedText(TagEnum.nomStatus, suffix));
605 }
606 tags.addAll(nomStatusTags);
607 return tags;
608
609 }
610
611 public List<TaggedText> getTaggedTitle(T nonViralName) {
612 if (nonViralName == null){
613 return null;
614 }
615
616 List<TaggedText> tags = new ArrayList<TaggedText>();
617
618 //TODO how to handle protected fullTitleCache here?
619
620 if (nonViralName.isProtectedTitleCache()){
621 //protected title cache
622 tags.add(new TaggedText(TagEnum.name, nonViralName.getTitleCache()));
623 return tags;
624 }else if (nonViralName.isHybridFormula()){
625 //hybrid formula
626 String hybridSeparator = NonViralNameParserImplRegExBase.hybridSign;
627 boolean isFirst = true;
628 List<HybridRelationship> rels = nonViralName.getOrderedChildRelationships();
629 for (HybridRelationship rel: rels){
630 if (! isFirst){
631 tags.add(new TaggedText(TagEnum.separator, hybridSeparator));
632 }
633 tags.add(new TaggedText(TagEnum.name, hybridSeparator));
634 isFirst = false;
635 tags.addAll(getTaggedTitle((T)rel.getParentName()));
636 }
637 return tags;
638 }else if (nonViralName.isAutonym()){
639 //Autonym
640 tags.addAll(handleTaggedAutonym(nonViralName));
641 }else{ //not Autonym
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));
649 }
650 }
651 }
652 return tags;
653
654 }
655
656
657 /**
658 * @param nonViralName
659 * @return
660 */
661 private List<TaggedText> getNameTags(T nonViralName) {
662 if (nonViralName == null){
663 return null;
664 }
665 List<TaggedText> tags = new ArrayList<TaggedText>();
666 Rank rank = nonViralName.getRank();
667
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);
684 }else{
685 logger.warn("Name Strategy for Name (UUID: " + nonViralName.getUuid() + ") not yet implemented");
686 }
687 //TODO handle appended phrase here instead of different places, check first if this is true for all
688 //cases
689
690 return tags;
691
692 }
693
694
695 //Old: may be replaced once getTagged(Full)Title is fully tested
696 /* (non-Javadoc)
697 * @see eu.etaxonomy.cdm.strategy.INameCacheStrategy#getTaggedName(eu.etaxonomy.cdm.model.common.CdmBase)
698 */
699 @Override
700 public List<Object> getTaggedName(T nonViralName) {
701 List<Object> tags = new ArrayList<Object>();
702
703 if (nonViralName.isProtectedNameCache() ||
704 nonViralName.isProtectedAuthorshipCache() ||
705 nonViralName.isProtectedFullTitleCache() ||
706 nonViralName.isProtectedTitleCache()){
707 tags.add(nonViralName.getTitleCache());
708 return tags;
709 }
710
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());
714 // }else{
715
716 if (nonViralName.getGenusOrUninomial() != null) {
717 tags.add(nonViralName.getGenusOrUninomial());
718 }
719 if (nonViralName.isSpecies() || nonViralName.isInfraSpecific()){
720 tags.add(nonViralName.getSpecificEpithet());
721 }
722
723 // No autonym
724 if (nonViralName.isInfraSpecific() && ! nonViralName.getSpecificEpithet().equals(nonViralName.getInfraSpecificEpithet())){
725 tags.add(nonViralName.getRank());
726 tags.add(nonViralName.getInfraSpecificEpithet());
727 }
728
729 if (nonViralName.isInfraGeneric()){
730 //TODO choose right strategy or generic approach?
731 // --- strategy 1 ---
732
733 if (nonViralName.getRank().isSpeciesAggregate()){
734 tags.add(nonViralName.getSpecificEpithet());
735 tags.add(getSpeciesAggregateEpithet(nonViralName));
736 }else{
737 tags.add(nonViralName.getRank());
738 tags.add(nonViralName.getInfraGenericEpithet());
739 }
740 // --- strategy 2 ---
741 // tags.add('('+nvn.getInfraGenericEpithet()+')');
742 }
743 Team authorTeam = Team.NewInstance();
744 authorTeam.setProtectedTitleCache(true);
745 authorTeam.setTitleCache(nonViralName.getAuthorshipCache(), true);
746 tags.add(authorTeam);
747
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());
752 }
753
754 if(! "".equals(nonViralName.getAppendedPhrase())&& (nonViralName.getAppendedPhrase() != null)){
755 tags.add(nonViralName.getAppendedPhrase());
756 }
757
758 return tags;
759 }
760
761
762 //***************************** PRIVATES ***************************************/
763
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));
769 }
770
771 String infraSpeciesEpi = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet()).trim().replace("null", "");
772 if (StringUtils.isNotBlank(infraSpeciesEpi)){
773 tags.add(new TaggedText(TagEnum.name, infraSpeciesEpi));
774 }
775
776 //result += " (rankless)";
777 addAppendedTaggedPhrase(tags, nonViralName);
778 return tags;
779 }
780
781 protected String getRanklessNameCache(NonViralName<?> nonViralName){
782 String result = "";
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);
789 return result;
790 }
791
792
793 protected List<TaggedText> getGenusOrUninomialTaggedNameCache(NonViralName<?> nonViralName){
794 List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
795 addAppendedTaggedPhrase(tags, nonViralName);
796 return tags;
797 }
798
799 protected String getGenusOrUninomialNameCache(NonViralName<?> nonViralName){
800 String result;
801 result = getUninomialPart(nonViralName);
802 result = addAppendedPhrase(result, nonViralName).trim();
803 return result;
804 }
805
806
807 private List<TaggedText> getUninomialTaggedPart(NonViralName<?> nonViralName) {
808 List<TaggedText> tags = new ArrayList<TaggedText>();
809
810 if (nonViralName.isMonomHybrid()){
811 addHybridPrefix(tags);
812 }
813
814 String uninomial = CdmUtils.Nz(nonViralName.getGenusOrUninomial()).trim().replace("null", "");
815 if (StringUtils.isNotBlank(uninomial)){
816 tags.add(new TaggedText(TagEnum.name, uninomial));
817 }
818
819 return tags;
820 }
821
822 private String getUninomialPart(NonViralName<?> nonViralName) {
823 String result;
824 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial()).trim();
825 if (nonViralName.isMonomHybrid()){
826 result = NonViralNameParserImplRegExBase.hybridSign + result;
827 }
828 return result;
829 }
830
831
832 protected List<TaggedText> getInfraGenusTaggedNameCache(NonViralName<?> nonViralName){
833 Rank rank = nonViralName.getRank();
834 if (rank.isSpeciesAggregate()){
835 return getSpeciesAggregateTaggedCache(nonViralName);
836 }
837
838 //genus
839 List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
840
841 //marker
842 String infraGenericMarker = "'unhandled infrageneric rank'";
843 if (rank != null){
844 try {
845 infraGenericMarker = rank.getInfraGenericMarker();
846 } catch (UnknownCdmTypeException e) {
847 infraGenericMarker = "'unhandled infrageneric rank'";
848 }
849 }
850 tags.add(new TaggedText(TagEnum.rank, infraGenericMarker));
851
852
853 String infraGenEpi = CdmUtils.Nz(nonViralName.getInfraGenericEpithet()).trim().replace("null", "");
854 if (StringUtils.isNotBlank(infraGenEpi)){
855 tags.add(new TaggedText(TagEnum.name, infraGenEpi));
856 }
857
858 addAppendedTaggedPhrase(tags, nonViralName);
859 return tags;
860 }
861
862 protected String getInfraGenusNameCache(NonViralName<?> nonViralName){
863 String result;
864 Rank rank = nonViralName.getRank();
865 if (rank.isSpeciesAggregate()){
866 return getSpeciesAggregateCache(nonViralName);
867 }
868 String infraGenericMarker = "'unhandled infrageneric rank'";
869 if (rank != null){
870 try {
871 infraGenericMarker = rank.getInfraGenericMarker();
872 } catch (UnknownCdmTypeException e) {
873 infraGenericMarker = "'unhandled infrageneric rank'";
874 }
875 }
876 result = getUninomialPart(nonViralName);
877 result += " " + infraGenericMarker + " " + (CdmUtils.Nz(nonViralName.getInfraGenericEpithet())).trim().replace("null", "");
878 result = addAppendedPhrase(result, nonViralName).trim();
879 return result;
880 }
881
882 // aggr.|agg.|group
883 protected List<TaggedText> getSpeciesAggregateTaggedCache(NonViralName<?> nonViralName){
884 List<TaggedText> tags = getGenusAndSpeciesTaggedPart(nonViralName);
885
886 addSpeciesAggregateTaggedEpithet(tags, nonViralName);
887 addAppendedTaggedPhrase(tags, nonViralName);
888 return tags;
889 }
890
891 private void addSpeciesAggregateTaggedEpithet(List<TaggedText> tags, NonViralName<?> nonViralName) {
892 String marker;
893 try {
894 marker = nonViralName.getRank().getInfraGenericMarker();
895 } catch (UnknownCdmTypeException e) {
896 marker = "'unknown aggregat type'";
897 }
898 if (StringUtils.isNotBlank(marker)){
899 tags.add(new TaggedText(TagEnum.rank, marker));
900 }
901 }
902
903 // aggr.|agg.|group
904 protected String getSpeciesAggregateCache(NonViralName<?> nonViralName){
905 String result = getGenusAndSpeciesPart(nonViralName);
906
907 result += " " + getSpeciesAggregateEpithet(nonViralName);
908 result = addAppendedPhrase(result, nonViralName).trim();
909 return result;
910 }
911
912 private String getSpeciesAggregateEpithet(NonViralName<?> nonViralName) {
913 String marker;
914 try {
915 marker = nonViralName.getRank().getInfraGenericMarker();
916 } catch (UnknownCdmTypeException e) {
917 marker = "'unknown aggregat type'";
918 }
919 return marker;
920 }
921
922
923 protected List<TaggedText> getSpeciesTaggedNameCache(NonViralName<?> nonViralName){
924 List<TaggedText> tags = getGenusAndSpeciesTaggedPart(nonViralName);
925 addAppendedTaggedPhrase(tags, nonViralName);
926 return tags;
927 }
928
929 protected String getSpeciesNameCache(NonViralName<?> nonViralName){
930 String result = getGenusAndSpeciesPart(nonViralName);
931 result = addAppendedPhrase(result, nonViralName).trim();
932 result = result.replace("\\s\\", " ");
933 return result;
934 }
935
936 protected List<TaggedText> getInfraSpeciesTaggedNameCache(NonViralName<?> nonViralName){
937 return getInfraSpeciesTaggedNameCache(nonViralName, true);
938 }
939
940 protected List<TaggedText> getInfraSpeciesTaggedNameCache(NonViralName<?> nonViralName, boolean includeMarker){
941 List<TaggedText> tags = getGenusAndSpeciesTaggedPart(nonViralName);
942 if (includeMarker){
943 String marker = (nonViralName.getRank().getAbbreviation()).trim().replace("null", "");
944 if (StringUtils.isNotBlank(marker)){
945 tags.add(new TaggedText(TagEnum.rank, marker));
946 }
947 }
948 String infrSpecEpi = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet());
949 if (nonViralName.isTrinomHybrid()){
950 addHybridPrefix(tags);
951 }
952
953 infrSpecEpi = infrSpecEpi.trim().replace("null", "");
954 if (StringUtils.isNotBlank(infrSpecEpi)){
955 tags.add(new TaggedText(TagEnum.name, infrSpecEpi));
956 }
957
958 addAppendedTaggedPhrase(tags, nonViralName);
959 return tags;
960 }
961
962
963 /**
964 * Adds a tag for the hybrid sign and an empty separator to avoid trailing whitespaces.
965 * @param tags
966 */
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
970 }
971
972 protected String getInfraSpeciesNameCache(NonViralName<?> nonViralName){
973 return getInfraSpeciesNameCache(nonViralName, true);
974 }
975
976
977 protected String getInfraSpeciesNameCache(NonViralName<?> nonViralName, boolean includeMarker){
978 String result = getGenusAndSpeciesPart(nonViralName);
979 if (includeMarker){
980 result += " " + (nonViralName.getRank().getAbbreviation()).trim().replace("null", "");
981 }
982 String infrSpecEpi = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet());
983 if (nonViralName.isTrinomHybrid()){
984 infrSpecEpi = NonViralNameParserImplRegExBase.hybridSign + infrSpecEpi;
985 }
986 result += " " + (infrSpecEpi).trim().replace("null", "");
987 result = addAppendedPhrase(result, nonViralName).trim();
988 return result;
989 }
990
991
992 private List<TaggedText> getGenusAndSpeciesTaggedPart(NonViralName<?> nonViralName) {
993 //Uninomial
994 List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
995
996 //InfraGenericEpi
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;
1003 }
1004 infrGenEpi = "(" + infrGenEpi + ")";
1005 tags.add(new TaggedText(TagEnum.name, infrGenEpi));
1006 }
1007
1008 //Species Epi
1009 String specEpi = CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim().replace("null", "");
1010 if (! hasInfraGenericEpi && nonViralName.isBinomHybrid() ||
1011 hasInfraGenericEpi && nonViralName.isTrinomHybrid()){
1012 addHybridPrefix(tags);
1013 }
1014 if (StringUtils.isNotBlank(specEpi)){
1015 tags.add(new TaggedText(TagEnum.name, specEpi));
1016 }
1017 return tags;
1018 }
1019
1020 private String getGenusAndSpeciesPart(NonViralName<?> nonViralName) {
1021 String result;
1022 //Uninomial
1023 result = getUninomialPart(nonViralName);
1024
1025 //InfraGenericEpi
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;
1031 }
1032 result += " (" + infrGenEpi + ")";
1033 }
1034 //Species Epi
1035 String specEpi = CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim();
1036 if (! hasInfraGenericEpi && nonViralName.isBinomHybrid() ||
1037 hasInfraGenericEpi && nonViralName.isTrinomHybrid()){
1038 specEpi = NonViralNameParserImplRegExBase.hybridSign + specEpi;
1039 }
1040 result += " " + (specEpi).replace("null", "");
1041 return result;
1042 }
1043
1044
1045 /**
1046 * Adds the tag for the appended phrase if an appended phrase exists
1047 * @param tags
1048 * @param nonViralName
1049 */
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));
1054 }
1055 }
1056
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;
1065 }else {
1066 return resultString + " " + appendedPhrase;
1067 }
1068 }
1069
1070
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();
1079 } else {
1080 return taxonNameBase.getInfraSpecificEpithet();
1081 }
1082 }
1083 }