no override for getNameCache
[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 public String getNameCache(T nonViralName) {
415 List<TaggedText> tags = getNameTags(nonViralName);
416 if (tags == null){
417 return null;
418 }else{
419 String result = createString(tags);
420 return result;
421 }
422 }
423
424 public String getNameCache_OLD(T nonViralName) {
425 if (nonViralName == null){
426 return null;
427 }
428 String result;
429 Rank rank = nonViralName.getRank();
430
431 if (nonViralName.isProtectedNameCache()){
432 result = nonViralName.getNameCache();
433 }else if (rank == null){
434 result = getRanklessNameCache(nonViralName);
435 // }else if (nonViralName.isInfragenericUnranked()){
436 // result = getUnrankedInfragenericNameCache(nonViralName);
437 }else if (rank.isInfraSpecific()){
438 result = getInfraSpeciesNameCache(nonViralName);
439 }else if (rank.isSpecies()){
440 result = getSpeciesNameCache(nonViralName);
441 }else if (rank.isInfraGeneric()){
442 result = getInfraGenusNameCache(nonViralName);
443 }else if (rank.isGenus()){
444 result = getGenusOrUninomialNameCache(nonViralName);
445 }else if (rank.isSupraGeneric()){
446 result = getGenusOrUninomialNameCache(nonViralName);
447 }else{
448 logger.warn("Name Strategy for Name (UUID: " + nonViralName.getUuid() + ") not yet implemented");
449 result = "";
450 }
451 return result;
452 }
453
454
455 private String getUnrankedInfragenericNameCache(T nonViralName) {
456 String result;
457 Rank rank = nonViralName.getRank();
458 if (rank.isSpeciesAggregate()){
459 return getSpeciesAggregateCache(nonViralName);
460 }
461 String infraGenericMarker = rank.getAbbreviation();
462 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial()).trim();
463 result += " " + infraGenericMarker + " " + (CdmUtils.Nz(nonViralName.getInfraGenericEpithet())).trim().replace("null", "");
464 result = addAppendedPhrase(result, nonViralName).trim();
465 return result;
466 }
467
468
469 /* (non-Javadoc)
470 * @see eu.etaxonomy.cdm.strategy.cache.INonViralNameCacheStrategy#getAuthorCache(eu.etaxonomy.cdm.model.name.NonViralName)
471 */
472 public String getAuthorshipCache(T nonViralName) {
473 if (nonViralName == null){
474 return null;
475 }
476 //cache protected
477 if (nonViralName.isProtectedAuthorshipCache() == true) {
478 return nonViralName.getAuthorshipCache();
479 }
480 return getNonCacheAuthorshipCache(nonViralName);
481
482 }
483
484 /**
485 * Returns the authorshipcache string for the atomized authorship fields. Does not use the authorshipfield.
486 * @throws NullPointerException if nonViralName is null.
487 * @param nonViralName
488 * @return
489 */
490 protected String getNonCacheAuthorshipCache(T nonViralName){
491 String result = "";
492 INomenclaturalAuthor combinationAuthor = nonViralName.getCombinationAuthorTeam();
493 INomenclaturalAuthor exCombinationAuthor = nonViralName.getExCombinationAuthorTeam();
494 INomenclaturalAuthor basionymAuthor = nonViralName.getBasionymAuthorTeam();
495 INomenclaturalAuthor exBasionymAuthor = nonViralName.getExBasionymAuthorTeam();
496 String basionymPart = "";
497 String authorPart = "";
498 //basionym
499 if (basionymAuthor != null || exBasionymAuthor != null){
500 basionymPart = BasionymStart + getAuthorAndExAuthor(basionymAuthor, exBasionymAuthor) + BasionymEnd;
501 }
502 if (combinationAuthor != null || exCombinationAuthor != null){
503 authorPart = getAuthorAndExAuthor(combinationAuthor, exCombinationAuthor);
504 }
505 result = CdmUtils.concat(BasionymAuthorCombinationAuthorSeperator, basionymPart, authorPart);
506 return result;
507 }
508
509 /**
510 * Returns the AuthorCache part for a combination of an author and an ex author. This applies on combination authors
511 * as well as on basionym/orginal combination authors.
512 * @param author the author
513 * @param exAuthor the ex-author
514 * @return
515 */
516 protected String getAuthorAndExAuthor(INomenclaturalAuthor author, INomenclaturalAuthor exAuthor){
517 String result = "";
518 String authorString = "";
519 String exAuthorString = "";
520 if (author != null){
521 authorString = CdmUtils.Nz(author.getNomenclaturalTitle());
522 }
523 if (exAuthor != null){
524 exAuthorString = CdmUtils.Nz(exAuthor.getNomenclaturalTitle());
525 }
526 if (exAuthorString.length() > 0 ){
527 exAuthorString = exAuthorString + ExAuthorSeperator;
528 }
529 result = exAuthorString + authorString;
530 return result;
531
532 }
533
534 // ************* TAGGED NAME ***************************************/
535
536 /* (non-Javadoc)
537 * @see eu.etaxonomy.cdm.strategy.cache.name.NameCacheStrategyBase#getTaggedTitle(eu.etaxonomy.cdm.model.name.TaxonNameBase)
538 */
539 @Override
540 public List<TaggedText> getTaggedFullTitle(T nonViralName) {
541 List<TaggedText> tags = new ArrayList<TaggedText>();
542
543 //null
544 if (nonViralName == null){
545 return null;
546 }
547
548 //protected full title cache
549 if (nonViralName.isProtectedFullTitleCache()){
550 tags.add(new TaggedText(TagEnum.fullName, nonViralName.getFullTitleCache()));
551 return tags;
552 }
553
554 //title cache
555 // String titleCache = nonViralName.getTitleCache();
556 List<TaggedText> titleTags = getTaggedTitle(nonViralName);
557 tags.addAll(titleTags);
558
559
560 //reference
561 String microReference = nonViralName.getNomenclaturalMicroReference();
562 INomenclaturalReference ref = nonViralName.getNomenclaturalReference();
563 String referenceBaseCache = null;
564 if (ref != null){
565 INomenclaturalReference nomenclaturalReference = HibernateProxyHelper.deproxy(ref, INomenclaturalReference.class);
566 nomenclaturalReference.setCacheStrategy(nomenclaturalReference.getType().getCacheStrategy());
567 referenceBaseCache = nomenclaturalReference.getNomenclaturalCitation(microReference);
568 }
569 //add to tags
570 if (StringUtils.isNotBlank(referenceBaseCache)){
571 if (! referenceBaseCache.trim().startsWith("in ")){
572 String refConcat = ", ";
573 tags.add(new TaggedText(TagEnum.separator, refConcat));
574 }
575 tags.add(new TaggedText(TagEnum.reference, referenceBaseCache));
576 }
577
578 //nomenclatural status
579 Set<NomenclaturalStatus> ncStati = nonViralName.getStatus();
580 Iterator<NomenclaturalStatus> iterator = ncStati.iterator();
581 List<TaggedText> nomStatusTags = new ArrayList<TaggedText>();
582 while (iterator.hasNext()) {
583 NomenclaturalStatus ncStatus = (NomenclaturalStatus)iterator.next();
584 // since the NewInstance method of nomencatural status allows null as parameter
585 // we have to check for null values here
586 String suffix = "not defined";
587 if(ncStatus.getType() != null){
588 NomenclaturalStatusType statusType = ncStatus.getType();
589 Language lang = Language.LATIN();
590 Representation repr = statusType.getRepresentation(lang);
591 if (repr != null){
592 suffix = repr.getAbbreviatedLabel();
593 }else{
594 String message = "No latin representation available for nom. status. " + statusType.getTitleCache();
595 logger.warn(message);
596 throw new IllegalStateException(message);
597 }
598 }else if(ncStatus.getRuleConsidered() != null && ! ncStatus.getRuleConsidered().equals("")){
599 suffix = ncStatus.getRuleConsidered();
600 }
601 String statusSeparator = ", ";
602 nomStatusTags.add(new TaggedText(TagEnum.separator, statusSeparator));
603 nomStatusTags.add(new TaggedText(TagEnum.nomStatus, suffix));
604 }
605 tags.addAll(nomStatusTags);
606 return tags;
607
608 }
609
610 public List<TaggedText> getTaggedTitle(T nonViralName) {
611 if (nonViralName == null){
612 return null;
613 }
614
615 List<TaggedText> tags = new ArrayList<TaggedText>();
616
617 //TODO how to handle protected fullTitleCache here?
618
619 if (nonViralName.isProtectedTitleCache()){
620 //protected title cache
621 tags.add(new TaggedText(TagEnum.name, nonViralName.getTitleCache()));
622 return tags;
623 }else if (nonViralName.isHybridFormula()){
624 //hybrid formula
625 String hybridSeparator = NonViralNameParserImplRegExBase.hybridSign;
626 boolean isFirst = true;
627 List<HybridRelationship> rels = nonViralName.getOrderedChildRelationships();
628 for (HybridRelationship rel: rels){
629 if (! isFirst){
630 tags.add(new TaggedText(TagEnum.separator, hybridSeparator));
631 }
632 tags.add(new TaggedText(TagEnum.name, hybridSeparator));
633 isFirst = false;
634 tags.addAll(getTaggedTitle((T)rel.getParentName()));
635 }
636 return tags;
637 }else if (nonViralName.isAutonym()){
638 //Autonym
639 tags.addAll(handleTaggedAutonym(nonViralName));
640 }else{ //not Autonym
641 // String nameCache = nonViralName.getNameCache(); //OLD: CdmUtils.Nz(getNameCache(nonViralName));
642 List<TaggedText> nameTags = getNameTags(nonViralName);
643 tags.addAll(nameTags);
644 if (nameIncludesAuthorship(nonViralName)){
645 String authorCache = getAuthorshipCache(nonViralName);
646 if (StringUtils.isNotBlank(authorCache)){
647 tags.add(new TaggedText(TagEnum.authors, authorCache));
648 }
649 }
650 }
651 return tags;
652
653 }
654
655
656 /**
657 * @param nonViralName
658 * @return
659 */
660 private List<TaggedText> getNameTags(T nonViralName) {
661 if (nonViralName == null){
662 return null;
663 }
664 List<TaggedText> tags = new ArrayList<TaggedText>();
665 Rank rank = nonViralName.getRank();
666
667 if (nonViralName.isProtectedNameCache()){
668 tags.add(new TaggedText(TagEnum.name, nonViralName.getNameCache()));
669 }else if (rank == null){
670 tags = getRanklessTaggedNameCache(nonViralName);
671 // }else if (nonViralName.isInfragenericUnranked()){
672 // result = getUnrankedInfragenericNameCache(nonViralName);
673 }else if (rank.isInfraSpecific()){
674 tags = getInfraSpeciesTaggedNameCache(nonViralName);
675 }else if (rank.isSpecies()){
676 tags = getSpeciesTaggedNameCache(nonViralName);
677 }else if (rank.isInfraGeneric()){
678 tags = getInfraGenusTaggedNameCache(nonViralName);
679 }else if (rank.isGenus()){
680 tags = getGenusOrUninomialTaggedNameCache(nonViralName);
681 }else if (rank.isSupraGeneric()){
682 tags = getGenusOrUninomialTaggedNameCache(nonViralName);
683 }else{
684 logger.warn("Name Strategy for Name (UUID: " + nonViralName.getUuid() + ") not yet implemented");
685 }
686 //TODO handle appended phrase here instead of different places, check first if this is true for all
687 //cases
688
689 return tags;
690
691 }
692
693
694 //Old: may be replaced once getTagged(Full)Title is fully tested
695 /* (non-Javadoc)
696 * @see eu.etaxonomy.cdm.strategy.INameCacheStrategy#getTaggedName(eu.etaxonomy.cdm.model.common.CdmBase)
697 */
698 @Override
699 public List<Object> getTaggedName(T nonViralName) {
700 List<Object> tags = new ArrayList<Object>();
701
702 if (nonViralName.isProtectedNameCache() ||
703 nonViralName.isProtectedAuthorshipCache() ||
704 nonViralName.isProtectedFullTitleCache() ||
705 nonViralName.isProtectedTitleCache()){
706 tags.add(nonViralName.getTitleCache());
707 return tags;
708 }
709
710 // Why does it make sense to add the nameCache in case of non existing genusOrUninomial?
711 // if (nonViralName.getGenusOrUninomial() == null){
712 // tags.add(nonViralName.getNameCache());
713 // }else{
714
715 if (nonViralName.getGenusOrUninomial() != null) {
716 tags.add(nonViralName.getGenusOrUninomial());
717 }
718 if (nonViralName.isSpecies() || nonViralName.isInfraSpecific()){
719 tags.add(nonViralName.getSpecificEpithet());
720 }
721
722 // No autonym
723 if (nonViralName.isInfraSpecific() && ! nonViralName.getSpecificEpithet().equals(nonViralName.getInfraSpecificEpithet())){
724 tags.add(nonViralName.getRank());
725 tags.add(nonViralName.getInfraSpecificEpithet());
726 }
727
728 if (nonViralName.isInfraGeneric()){
729 //TODO choose right strategy or generic approach?
730 // --- strategy 1 ---
731
732 if (nonViralName.getRank().isSpeciesAggregate()){
733 tags.add(nonViralName.getSpecificEpithet());
734 tags.add(getSpeciesAggregateEpithet(nonViralName));
735 }else{
736 tags.add(nonViralName.getRank());
737 tags.add(nonViralName.getInfraGenericEpithet());
738 }
739 // --- strategy 2 ---
740 // tags.add('('+nvn.getInfraGenericEpithet()+')');
741 }
742 Team authorTeam = Team.NewInstance();
743 authorTeam.setProtectedTitleCache(true);
744 authorTeam.setTitleCache(nonViralName.getAuthorshipCache(), true);
745 tags.add(authorTeam);
746
747 // Name is an autonym. Rank and infraspecific epitheton follow the author
748 if (nonViralName.isInfraSpecific() && nonViralName.getSpecificEpithet().equals(nonViralName.getInfraSpecificEpithet())){
749 tags.add(nonViralName.getRank());
750 tags.add(nonViralName.getInfraSpecificEpithet());
751 }
752
753 if(! "".equals(nonViralName.getAppendedPhrase())&& (nonViralName.getAppendedPhrase() != null)){
754 tags.add(nonViralName.getAppendedPhrase());
755 }
756
757 return tags;
758 }
759
760
761 //***************************** PRIVATES ***************************************/
762
763 protected List<TaggedText> getRanklessTaggedNameCache(NonViralName<?> nonViralName){
764 List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
765 String speciesEpi = CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim().replace("null", "");
766 if (StringUtils.isNotBlank(speciesEpi)){
767 tags.add(new TaggedText(TagEnum.name, speciesEpi));
768 }
769
770 String infraSpeciesEpi = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet()).trim().replace("null", "");
771 if (StringUtils.isNotBlank(infraSpeciesEpi)){
772 tags.add(new TaggedText(TagEnum.name, infraSpeciesEpi));
773 }
774
775 //result += " (rankless)";
776 addAppendedTaggedPhrase(tags, nonViralName);
777 return tags;
778 }
779
780 protected String getRanklessNameCache(NonViralName<?> nonViralName){
781 String result = "";
782 result = (result + (CdmUtils.Nz(nonViralName.getGenusOrUninomial()))).trim().replace("null", "");
783 result += " " + (CdmUtils.Nz(nonViralName.getSpecificEpithet())).trim();
784 result += " " + (CdmUtils.Nz(nonViralName.getInfraSpecificEpithet())).trim();
785 result = result.trim().replace("null", "");
786 //result += " (rankless)";
787 result = addAppendedPhrase(result, nonViralName);
788 return result;
789 }
790
791
792 protected List<TaggedText> getGenusOrUninomialTaggedNameCache(NonViralName<?> nonViralName){
793 List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
794 addAppendedTaggedPhrase(tags, nonViralName);
795 return tags;
796 }
797
798 protected String getGenusOrUninomialNameCache(NonViralName<?> nonViralName){
799 String result;
800 result = getUninomialPart(nonViralName);
801 result = addAppendedPhrase(result, nonViralName).trim();
802 return result;
803 }
804
805
806 private List<TaggedText> getUninomialTaggedPart(NonViralName<?> nonViralName) {
807 List<TaggedText> tags = new ArrayList<TaggedText>();
808
809 if (nonViralName.isMonomHybrid()){
810 addHybridPrefix(tags);
811 }
812
813 String uninomial = CdmUtils.Nz(nonViralName.getGenusOrUninomial()).trim().replace("null", "");
814 if (StringUtils.isNotBlank(uninomial)){
815 tags.add(new TaggedText(TagEnum.name, uninomial));
816 }
817
818 return tags;
819 }
820
821 private String getUninomialPart(NonViralName<?> nonViralName) {
822 String result;
823 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial()).trim();
824 if (nonViralName.isMonomHybrid()){
825 result = NonViralNameParserImplRegExBase.hybridSign + result;
826 }
827 return result;
828 }
829
830
831 protected List<TaggedText> getInfraGenusTaggedNameCache(NonViralName<?> nonViralName){
832 Rank rank = nonViralName.getRank();
833 if (rank.isSpeciesAggregate()){
834 return getSpeciesAggregateTaggedCache(nonViralName);
835 }
836
837 //genus
838 List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
839
840 //marker
841 String infraGenericMarker = "'unhandled infrageneric rank'";
842 if (rank != null){
843 try {
844 infraGenericMarker = rank.getInfraGenericMarker();
845 } catch (UnknownCdmTypeException e) {
846 infraGenericMarker = "'unhandled infrageneric rank'";
847 }
848 }
849 tags.add(new TaggedText(TagEnum.rank, infraGenericMarker));
850
851
852 String infraGenEpi = CdmUtils.Nz(nonViralName.getInfraGenericEpithet()).trim().replace("null", "");
853 if (StringUtils.isNotBlank(infraGenEpi)){
854 tags.add(new TaggedText(TagEnum.name, infraGenEpi));
855 }
856
857 addAppendedTaggedPhrase(tags, nonViralName);
858 return tags;
859 }
860
861 protected String getInfraGenusNameCache(NonViralName<?> nonViralName){
862 String result;
863 Rank rank = nonViralName.getRank();
864 if (rank.isSpeciesAggregate()){
865 return getSpeciesAggregateCache(nonViralName);
866 }
867 String infraGenericMarker = "'unhandled infrageneric rank'";
868 if (rank != null){
869 try {
870 infraGenericMarker = rank.getInfraGenericMarker();
871 } catch (UnknownCdmTypeException e) {
872 infraGenericMarker = "'unhandled infrageneric rank'";
873 }
874 }
875 result = getUninomialPart(nonViralName);
876 result += " " + infraGenericMarker + " " + (CdmUtils.Nz(nonViralName.getInfraGenericEpithet())).trim().replace("null", "");
877 result = addAppendedPhrase(result, nonViralName).trim();
878 return result;
879 }
880
881 // aggr.|agg.|group
882 protected List<TaggedText> getSpeciesAggregateTaggedCache(NonViralName<?> nonViralName){
883 List<TaggedText> tags = getGenusAndSpeciesTaggedPart(nonViralName);
884
885 addSpeciesAggregateTaggedEpithet(tags, nonViralName);
886 addAppendedTaggedPhrase(tags, nonViralName);
887 return tags;
888 }
889
890 private void addSpeciesAggregateTaggedEpithet(List<TaggedText> tags, NonViralName<?> nonViralName) {
891 String marker;
892 try {
893 marker = nonViralName.getRank().getInfraGenericMarker();
894 } catch (UnknownCdmTypeException e) {
895 marker = "'unknown aggregat type'";
896 }
897 if (StringUtils.isNotBlank(marker)){
898 tags.add(new TaggedText(TagEnum.rank, marker));
899 }
900 }
901
902 // aggr.|agg.|group
903 protected String getSpeciesAggregateCache(NonViralName<?> nonViralName){
904 String result = getGenusAndSpeciesPart(nonViralName);
905
906 result += " " + getSpeciesAggregateEpithet(nonViralName);
907 result = addAppendedPhrase(result, nonViralName).trim();
908 return result;
909 }
910
911 private String getSpeciesAggregateEpithet(NonViralName<?> nonViralName) {
912 String marker;
913 try {
914 marker = nonViralName.getRank().getInfraGenericMarker();
915 } catch (UnknownCdmTypeException e) {
916 marker = "'unknown aggregat type'";
917 }
918 return marker;
919 }
920
921
922 protected List<TaggedText> getSpeciesTaggedNameCache(NonViralName<?> nonViralName){
923 List<TaggedText> tags = getGenusAndSpeciesTaggedPart(nonViralName);
924 addAppendedTaggedPhrase(tags, nonViralName);
925 return tags;
926 }
927
928 protected String getSpeciesNameCache(NonViralName<?> nonViralName){
929 String result = getGenusAndSpeciesPart(nonViralName);
930 result = addAppendedPhrase(result, nonViralName).trim();
931 result = result.replace("\\s\\", " ");
932 return result;
933 }
934
935 protected List<TaggedText> getInfraSpeciesTaggedNameCache(NonViralName<?> nonViralName){
936 return getInfraSpeciesTaggedNameCache(nonViralName, true);
937 }
938
939 protected List<TaggedText> getInfraSpeciesTaggedNameCache(NonViralName<?> nonViralName, boolean includeMarker){
940 List<TaggedText> tags = getGenusAndSpeciesTaggedPart(nonViralName);
941 if (includeMarker){
942 String marker = (nonViralName.getRank().getAbbreviation()).trim().replace("null", "");
943 if (StringUtils.isNotBlank(marker)){
944 tags.add(new TaggedText(TagEnum.rank, marker));
945 }
946 }
947 String infrSpecEpi = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet());
948 if (nonViralName.isTrinomHybrid()){
949 addHybridPrefix(tags);
950 }
951
952 infrSpecEpi = infrSpecEpi.trim().replace("null", "");
953 if (StringUtils.isNotBlank(infrSpecEpi)){
954 tags.add(new TaggedText(TagEnum.name, infrSpecEpi));
955 }
956
957 addAppendedTaggedPhrase(tags, nonViralName);
958 return tags;
959 }
960
961
962 /**
963 * Adds a tag for the hybrid sign and an empty separator to avoid trailing whitespaces.
964 * @param tags
965 */
966 private void addHybridPrefix(List<TaggedText> tags) {
967 tags.add(new TaggedText(TagEnum.hybridSign, NonViralNameParserImplRegExBase.hybridSign));
968 tags.add(new TaggedText(TagEnum.separator, "")); //no whitespace separator
969 }
970
971 protected String getInfraSpeciesNameCache(NonViralName<?> nonViralName){
972 return getInfraSpeciesNameCache(nonViralName, true);
973 }
974
975
976 protected String getInfraSpeciesNameCache(NonViralName<?> nonViralName, boolean includeMarker){
977 String result = getGenusAndSpeciesPart(nonViralName);
978 if (includeMarker){
979 result += " " + (nonViralName.getRank().getAbbreviation()).trim().replace("null", "");
980 }
981 String infrSpecEpi = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet());
982 if (nonViralName.isTrinomHybrid()){
983 infrSpecEpi = NonViralNameParserImplRegExBase.hybridSign + infrSpecEpi;
984 }
985 result += " " + (infrSpecEpi).trim().replace("null", "");
986 result = addAppendedPhrase(result, nonViralName).trim();
987 return result;
988 }
989
990
991 private List<TaggedText> getGenusAndSpeciesTaggedPart(NonViralName<?> nonViralName) {
992 //Uninomial
993 List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
994
995 //InfraGenericEpi
996 boolean hasInfraGenericEpi = StringUtils.isNotBlank(nonViralName.getInfraGenericEpithet());
997 if (hasInfraGenericEpi){
998 String infrGenEpi = nonViralName.getInfraGenericEpithet().trim();
999 if (nonViralName.isBinomHybrid()){
1000 // addHybridPrefix(tags); FIXME hybridSign should be tag, but then we need to handle "(" ")" differently.
1001 infrGenEpi = NonViralNameParserImplRegExBase.hybridSign + infrGenEpi;
1002 }
1003 infrGenEpi = "(" + infrGenEpi + ")";
1004 tags.add(new TaggedText(TagEnum.name, infrGenEpi));
1005 }
1006
1007 //Species Epi
1008 String specEpi = CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim().replace("null", "");
1009 if (! hasInfraGenericEpi && nonViralName.isBinomHybrid() ||
1010 hasInfraGenericEpi && nonViralName.isTrinomHybrid()){
1011 addHybridPrefix(tags);
1012 }
1013 if (StringUtils.isNotBlank(specEpi)){
1014 tags.add(new TaggedText(TagEnum.name, specEpi));
1015 }
1016 return tags;
1017 }
1018
1019 private String getGenusAndSpeciesPart(NonViralName<?> nonViralName) {
1020 String result;
1021 //Uninomial
1022 result = getUninomialPart(nonViralName);
1023
1024 //InfraGenericEpi
1025 boolean hasInfraGenericEpi = StringUtils.isNotBlank(nonViralName.getInfraGenericEpithet());
1026 if (hasInfraGenericEpi){
1027 String infrGenEpi = nonViralName.getInfraGenericEpithet().trim();
1028 if (nonViralName.isBinomHybrid()){
1029 infrGenEpi = NonViralNameParserImplRegExBase.hybridSign + infrGenEpi;
1030 }
1031 result += " (" + infrGenEpi + ")";
1032 }
1033 //Species Epi
1034 String specEpi = CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim();
1035 if (! hasInfraGenericEpi && nonViralName.isBinomHybrid() ||
1036 hasInfraGenericEpi && nonViralName.isTrinomHybrid()){
1037 specEpi = NonViralNameParserImplRegExBase.hybridSign + specEpi;
1038 }
1039 result += " " + (specEpi).replace("null", "");
1040 return result;
1041 }
1042
1043
1044 /**
1045 * Adds the tag for the appended phrase if an appended phrase exists
1046 * @param tags
1047 * @param nonViralName
1048 */
1049 protected void addAppendedTaggedPhrase(List<TaggedText> tags, NonViralName<?> nonViralName){
1050 String appendedPhrase = nonViralName ==null ? null : nonViralName.getAppendedPhrase();
1051 if (StringUtils.isNotEmpty(appendedPhrase)){
1052 tags.add(new TaggedText(TagEnum.name, appendedPhrase));
1053 }
1054 }
1055
1056 protected String addAppendedPhrase(String resultString, NonViralName<?> nonViralName){
1057 String appendedPhrase = nonViralName ==null ? null : nonViralName.getAppendedPhrase();
1058 if (resultString == null){
1059 return appendedPhrase;
1060 }else if(appendedPhrase == null || "".equals(appendedPhrase.trim())) {
1061 return resultString;
1062 }else if ("".equals(resultString)){
1063 return resultString + appendedPhrase;
1064 }else {
1065 return resultString + " " + appendedPhrase;
1066 }
1067 }
1068
1069
1070 public String getLastEpithet(T taxonNameBase) {
1071 Rank rank = taxonNameBase.getRank();
1072 if(rank.isGenus() || rank.isSupraGeneric()) {
1073 return taxonNameBase.getGenusOrUninomial();
1074 } else if(rank.isInfraGeneric()) {
1075 return taxonNameBase.getInfraGenericEpithet();
1076 } else if(rank.isSpecies()) {
1077 return taxonNameBase.getSpecificEpithet();
1078 } else {
1079 return taxonNameBase.getInfraSpecificEpithet();
1080 }
1081 }
1082 }