Project

General

Profile

« Previous | Next » 

Revision 063510dc

Added by Andreas Müller about 7 years ago

ref #6630 unify ViralNameDefaultCacheStrategy with NonViralNameDefaultCacheStrategy

View differences:

cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/name/TaxonName.java
85 85
import eu.etaxonomy.cdm.strategy.cache.TaggedText;
86 86
import eu.etaxonomy.cdm.strategy.cache.name.CacheUpdate;
87 87
import eu.etaxonomy.cdm.strategy.cache.name.INameCacheStrategy;
88
import eu.etaxonomy.cdm.strategy.cache.name.NonViralNameDefaultCacheStrategy;
89
import eu.etaxonomy.cdm.strategy.cache.name.ViralNameDefaultCacheStrategy;
88
import eu.etaxonomy.cdm.strategy.cache.name.TaxonNameDefaultCacheStrategy;
90 89
import eu.etaxonomy.cdm.strategy.match.IMatchable;
91 90
import eu.etaxonomy.cdm.strategy.match.Match;
92 91
import eu.etaxonomy.cdm.strategy.match.Match.ReplaceMode;
......
607 606
     * Class constructor: creates a new taxon name instance
608 607
     * only containing its {@link Rank rank} and
609 608
     * its {@link HomotypicalGroup homotypical group} and
610
     * the {@link eu.etaxonomy.cdm.strategy.cache.name.NonViralNameDefaultCacheStrategy default cache strategy}.
609
     * the {@link eu.etaxonomy.cdm.strategy.cache.name.TaxonNameDefaultCacheStrategy default cache strategy}.
611 610
     * The new taxon name will be also added to the set of taxon names
612 611
     * belonging to this homotypical group.
613 612
     *
......
636 635
     * its {@link HomotypicalGroup homotypical group},
637 636
     * its scientific name components, its {@link eu.etaxonomy.cdm.model.agent.TeamOrPersonBase author(team)},
638 637
     * its {@link eu.etaxonomy.cdm.model.reference.Reference nomenclatural reference} and
639
     * the {@link eu.etaxonomy.cdm.strategy.cache.name.NonViralNameDefaultCacheStrategy default cache strategy}.
638
     * the {@link eu.etaxonomy.cdm.strategy.cache.name.TaxonNameDefaultCacheStrategy default cache strategy}.
640 639
     * The new non viral taxon name instance will be also added to the set of
641 640
     * non viral taxon names belonging to this homotypical group.
642 641
     *
......
679 678
        }else if (this.cacheStrategy != null){
680 679
           //
681 680
        }else if (getNameType() == NomenclaturalCode.NonViral){
682
            this.cacheStrategy = NonViralNameDefaultCacheStrategy.NewInstance();
681
            this.cacheStrategy = TaxonNameDefaultCacheStrategy.NewInstance();
683 682
        }else if (getNameType().isBotanical()){
684
            this.cacheStrategy = NonViralNameDefaultCacheStrategy.NewInstance();
683
            this.cacheStrategy = TaxonNameDefaultCacheStrategy.NewInstance();
685 684
        }else if (getNameType() == NomenclaturalCode.ICZN){
686
            this.cacheStrategy = NonViralNameDefaultCacheStrategy.NewInstance();
685
            this.cacheStrategy = TaxonNameDefaultCacheStrategy.NewInstance();
687 686
        }else if (getNameType() == NomenclaturalCode.ICNB){
688
            this.cacheStrategy = NonViralNameDefaultCacheStrategy.NewInstance();;
687
            this.cacheStrategy = TaxonNameDefaultCacheStrategy.NewInstance();
689 688
        }else if (getNameType() == NomenclaturalCode.ICVCN){
690
            this.cacheStrategy = ViralNameDefaultCacheStrategy.NewInstance();
689
            this.cacheStrategy = TaxonNameDefaultCacheStrategy.NewInstance();
691 690
        }
692 691
    }
693 692

  
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/name/TaxonNameFactory.java
37 37
    /**
38 38
     * Creates a new non viral taxon name instance
39 39
     * only containing its {@link common.Rank rank} and
40
      * the {@link eu.etaxonomy.cdm.strategy.cache.name.NonViralNameDefaultCacheStrategy default cache strategy}.
40
      * the {@link eu.etaxonomy.cdm.strategy.cache.name.TaxonNameDefaultCacheStrategy default cache strategy}.
41 41
     *
42 42
     * @param  rank  the rank to be assigned to <i>this</i> non viral taxon name
43 43
     * @see    #NewInstance(Rank, HomotypicalGroup)
......
56 56
     * Creates a new non viral taxon name instance
57 57
     * only containing its {@link common.Rank rank},
58 58
     * its {@link HomotypicalGroup homotypical group} and
59
      * the {@link eu.etaxonomy.cdm.strategy.cache.name.NonViralNameDefaultCacheStrategy default cache strategy}.
59
      * the {@link eu.etaxonomy.cdm.strategy.cache.name.TaxonNameDefaultCacheStrategy default cache strategy}.
60 60
     * The new non viral taxon name instance will be also added to the set of
61 61
     * non viral taxon names belonging to this homotypical group.
62 62
     *
......
88 88
    /**
89 89
     * Creates a new bacterial taxon name instance
90 90
     * only containing its {@link Rank rank} and
91
     * the {@link eu.etaxonomy.cdm.strategy.cache.name.NonViralNameDefaultCacheStrategy default cache strategy}.
91
     * the {@link eu.etaxonomy.cdm.strategy.cache.name.TaxonNameDefaultCacheStrategy default cache strategy}.
92 92
     *
93 93
     * @param  rank  the rank to be assigned to <i>this</i> bacterial taxon name
94 94
     * @see    #NewInstance(Rank, HomotypicalGroup)
......
105 105
     * Creates a new bacterial taxon name instance
106 106
     * only containing its {@link Rank rank},
107 107
     * its {@link HomotypicalGroup homotypical group} and
108
     * the {@link eu.etaxonomy.cdm.strategy.cache.name.NonViralNameDefaultCacheStrategy default cache strategy}.
108
     * the {@link eu.etaxonomy.cdm.strategy.cache.name.TaxonNameDefaultCacheStrategy default cache strategy}.
109 109
     * The new bacterial taxon name instance will be also added to the set of
110 110
     * bacterial taxon names belonging to this homotypical group.
111 111
     *
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.common.UTF8;
22
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
23
import eu.etaxonomy.cdm.model.agent.INomenclaturalAuthor;
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.INonViralName;
28
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
29
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
30
import eu.etaxonomy.cdm.model.name.Rank;
31
import eu.etaxonomy.cdm.model.name.TaxonName;
32
import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
33
import eu.etaxonomy.cdm.model.reference.Reference;
34
import eu.etaxonomy.cdm.strategy.cache.TagEnum;
35
import eu.etaxonomy.cdm.strategy.cache.TaggedText;
36
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
37
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImplRegExBase;
38

  
39

  
40
/**
41
 * This class is a default implementation for the INonViralNameCacheStrategy<T extends NonViralName>
42
 * interface.<BR>
43
 * The method implements a cache strategy for botanical names so no method has to be overwritten by
44
 * a subclass for botanic names.
45
 * Where differing from this default botanic name strategy other subclasses should overwrite the
46
 * existing methods, e.g. a CacheStrategy for zoological names should overwrite getAuthorAndExAuthor
47
 * @author a.mueller
48
 */
49
public class NonViralNameDefaultCacheStrategy
50
        extends NameCacheStrategyBase
51
        implements INonViralNameCacheStrategy {
52

  
53
    private static final Logger logger = Logger.getLogger(NonViralNameDefaultCacheStrategy.class);
54
	private static final long serialVersionUID = -6577757501563212669L;
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
    private static String NOTHO = "notho";
63
    protected CharSequence basionymAuthorCombinationAuthorSeperator = " ";
64

  
65
    protected String zooAuthorYearSeperator = ", ";
66

  
67

  
68

  
69
    @Override
70
    public  UUID getUuid(){
71
        return uuid;
72
    }
73

  
74
// ************************** FACTORY  ******************************/
75

  
76
    public static NonViralNameDefaultCacheStrategy NewInstance(){
77
        return new NonViralNameDefaultCacheStrategy();
78
    }
79

  
80

  
81
// ************ CONSTRUCTOR *******************/
82

  
83
    protected NonViralNameDefaultCacheStrategy(){
84
        super();
85
    }
86

  
87
/* **************** GETTER / SETTER **************************************/
88

  
89
    /**
90
     * String that separates the NameCache part from the AuthorCache part
91
     * @return
92
     */
93
    public String getNameAuthorSeperator() {
94
        return nameAuthorSeperator;
95
    }
96
    public void setNameAuthorSeperator(String nameAuthorSeperator) {
97
        this.nameAuthorSeperator = nameAuthorSeperator;
98
    }
99

  
100

  
101
    /**
102
     * String the basionym author part starts with e.g. '('.
103
     * This should correspond with the {@link NonViralNameDefaultCacheStrategy#getBasionymEnd() basionymEnd} attribute
104
     * @return
105
     */
106
    public String getBasionymStart() {
107
        return basionymStart;
108
    }
109
    public void setBasionymStart(String basionymStart) {
110
        this.basionymStart = basionymStart;
111
    }
112

  
113
    /**
114
     * String the basionym author part ends with e.g. ')'.
115
     * This should correspond with the {@link NonViralNameDefaultCacheStrategy#getBasionymStart() basionymStart} attribute
116
     * @return
117
     */
118
    public String getBasionymEnd() {
119
        return basionymEnd;
120
    }
121
    public void setBasionymEnd(String basionymEnd) {
122
        this.basionymEnd = basionymEnd;
123
    }
124

  
125

  
126
    /**
127
     * String to separate ex author from author.
128
     * @return
129
     */
130
    public String getExAuthorSeperator() {
131
        return exAuthorSeperator;
132
    }
133
    public void setExAuthorSeperator(String exAuthorSeperator) {
134
        this.exAuthorSeperator = exAuthorSeperator;
135
    }
136

  
137

  
138
    /**
139
     * String that separates the basionym/original_combination author part from the combination author part
140
     * @return
141
     */
142
    public CharSequence getBasionymAuthorCombinationAuthorSeperator() {
143
        return basionymAuthorCombinationAuthorSeperator;
144
    }
145

  
146

  
147
    public void setBasionymAuthorCombinationAuthorSeperator( CharSequence basionymAuthorCombinationAuthorSeperator) {
148
        this.basionymAuthorCombinationAuthorSeperator = basionymAuthorCombinationAuthorSeperator;
149
    }
150

  
151
    public String getZooAuthorYearSeperator() {
152
        return zooAuthorYearSeperator;
153
    }
154
    public void setZooAuthorYearSeperator(String authorYearSeperator) {
155
        this.zooAuthorYearSeperator = authorYearSeperator;
156
    }
157

  
158

  
159
//** *****************************************************************************************/
160

  
161

  
162

  
163

  
164
// ******************* Authorship ******************************/
165

  
166
    @Override
167
    public String getAuthorshipCache(TaxonName taxonName) {
168
        if (taxonName == null){
169
            return null;
170
        }
171
        //cache protected
172
        if (taxonName.isProtectedAuthorshipCache() == true) {
173
            return taxonName.getAuthorshipCache();
174
        }
175
        return getNonCacheAuthorshipCache(taxonName);
176
    }
177

  
178
    /**
179
     * Returns the authorshipcache string for the atomized authorship fields. Does not use the authorship field.
180
     * @throws NullPointerException if nonViralName is null.
181
     * @param nonViralName
182
     * @return
183
     */
184
    protected String getNonCacheAuthorshipCache(TaxonName nonViralName){
185
        if (nonViralName.getNameType().isZoological()){
186
            return this.getZoologicalNonCacheAuthorshipCache(nonViralName);
187
        }else{
188
            String result = "";
189
            INomenclaturalAuthor combinationAuthor = nonViralName.getCombinationAuthorship();
190
            INomenclaturalAuthor exCombinationAuthor = nonViralName.getExCombinationAuthorship();
191
            INomenclaturalAuthor basionymAuthor = nonViralName.getBasionymAuthorship();
192
            INomenclaturalAuthor exBasionymAuthor = nonViralName.getExBasionymAuthorship();
193
            String basionymPart = "";
194
            String authorPart = "";
195
            //basionym
196
            if (basionymAuthor != null || exBasionymAuthor != null){
197
                basionymPart = basionymStart + getAuthorAndExAuthor(basionymAuthor, exBasionymAuthor) + basionymEnd;
198
            }
199
            if (combinationAuthor != null || exCombinationAuthor != null){
200
                authorPart = getAuthorAndExAuthor(combinationAuthor, exCombinationAuthor);
201
            }
202
            result = CdmUtils.concat(basionymAuthorCombinationAuthorSeperator, basionymPart, authorPart);
203
//        if ("".equals(result)){
204
//        	result = null;
205
//        }
206
            return result;
207
        }
208
    }
209

  
210
    protected String getZoologicalNonCacheAuthorshipCache(TaxonName nonViralName) {
211
        if (nonViralName == null){
212
            return null;
213
        }
214
        String result = "";
215
        INomenclaturalAuthor combinationAuthor = nonViralName.getCombinationAuthorship();
216
        INomenclaturalAuthor exCombinationAuthor = nonViralName.getExCombinationAuthorship();
217
        INomenclaturalAuthor basionymAuthor = nonViralName.getBasionymAuthorship();
218
        INomenclaturalAuthor exBasionymAuthor = nonViralName.getExBasionymAuthorship();
219
        Integer publicationYear = nonViralName.getPublicationYear();
220
        Integer originalPublicationYear = nonViralName.getOriginalPublicationYear();
221

  
222
        String basionymPart = "";
223
        String authorPart = "";
224
        //basionym
225
        if (basionymAuthor != null || exBasionymAuthor != null || originalPublicationYear != null ){
226
            String authorAndEx = getAuthorAndExAuthor(basionymAuthor, exBasionymAuthor);
227
            String originalPublicationYearString = originalPublicationYear == null ? null : String.valueOf(originalPublicationYear);
228
            String authorAndExAndYear = CdmUtils.concat(zooAuthorYearSeperator, authorAndEx, originalPublicationYearString );
229
            basionymPart = basionymStart + authorAndExAndYear + basionymEnd;
230
        }
231
        if (combinationAuthor != null || exCombinationAuthor != null){
232
            String authorAndEx = getAuthorAndExAuthor(combinationAuthor, exCombinationAuthor);
233
            String publicationYearString = publicationYear == null ? null : String.valueOf(publicationYear);
234
            authorPart = CdmUtils.concat(zooAuthorYearSeperator, authorAndEx, publicationYearString);
235
        }
236
        result = CdmUtils.concat(basionymAuthorCombinationAuthorSeperator, basionymPart, authorPart);
237
        if (result == null){
238
            result = "";
239
        }
240
        return result;
241
    }
242

  
243

  
244
    /**
245
     * Returns the AuthorCache part for a combination of an author and an ex author. This applies on
246
     * combination authors as well as on basionym/orginal combination authors.
247
     * The correct order is exAuthor ex author though some botanist do not know about and do it the
248
     * other way round. (see 46.4-46.6 ICBN (Vienna Code, 2006))
249
     *
250
     * @param author the author
251
     * @param exAuthor the ex-author
252
     * @return
253
     */
254
    protected String getAuthorAndExAuthor(INomenclaturalAuthor author, INomenclaturalAuthor exAuthor){
255
        String authorString = "";
256
        String exAuthorString = "";
257
        if (author != null){
258
            authorString = CdmUtils.Nz(author.getNomenclaturalTitle());
259
        }
260
        if (exAuthor != null){
261
            exAuthorString = CdmUtils.Nz(exAuthor.getNomenclaturalTitle());
262
            exAuthorString += exAuthorSeperator;
263
        }
264
        String result = exAuthorString + authorString;
265
        return result;
266
    }
267

  
268

  
269

  
270
    /**
271
     * Checks if the given name should include the author in it's cached version.<BR>
272
     * This is usually the case but not for <i>species aggregates</i>.
273
     * @param nonViralName
274
     * @return
275
     */
276
    protected boolean nameIncludesAuthorship(INonViralName nonViralName){
277
        Rank rank = nonViralName.getRank();
278
        if (rank != null && rank.isSpeciesAggregate()){
279
            return false;
280
        }else{
281
            return true;
282
        }
283
    }
284

  
285
// ************* TAGGED NAME ***************************************/
286

  
287
    @Override
288
    public List<TaggedText> getTaggedFullTitle(TaxonName nonViralName) {
289
        List<TaggedText> tags = new ArrayList<>();
290

  
291
        //null
292
        if (nonViralName == null){
293
            return null;
294
        }
295

  
296
        //protected full title cache
297
        if (nonViralName.isProtectedFullTitleCache()){
298
            tags.add(new TaggedText(TagEnum.fullName, nonViralName.getFullTitleCache()));
299
            return tags;
300
        }
301

  
302
        //title cache
303
//		String titleCache = nonViralName.getTitleCache();
304
        List<TaggedText> titleTags = getTaggedTitle(nonViralName);
305
        tags.addAll(titleTags);
306

  
307
        //reference
308
        String microReference = nonViralName.getNomenclaturalMicroReference();
309
        INomenclaturalReference ref = nonViralName.getNomenclaturalReference();
310
        String referenceCache = null;
311
        if (ref != null){
312
            Reference reference = HibernateProxyHelper.deproxy(ref, Reference.class);
313
            referenceCache = reference.getNomenclaturalCitation(microReference);
314
        }
315
            //add to tags
316
        if (StringUtils.isNotBlank(referenceCache)){
317
            if (! referenceCache.trim().startsWith("in ")){
318
                String refConcat = ", ";
319
                tags.add(new TaggedText(TagEnum.separator, refConcat));
320
            }
321
            tags.add(new TaggedText(TagEnum.reference, referenceCache));
322
        }
323

  
324
        addOriginalSpelling(tags, nonViralName);
325

  
326
        //nomenclatural status
327
        tags.addAll(getNomStatusTags(nonViralName, true, false));
328
        return tags;
329

  
330
    }
331

  
332

  
333
    /**
334
     * @param nonViralName
335
     * @param tags
336
     * @return
337
     */
338
    @Override
339
    public List<TaggedText> getNomStatusTags(TaxonName nonViralName, boolean includeSeparatorBefore,
340
            boolean includeSeparatorAfter) {
341

  
342
        Set<NomenclaturalStatus> ncStati = nonViralName.getStatus();
343
        Iterator<NomenclaturalStatus> iterator = ncStati.iterator();
344
        List<TaggedText> nomStatusTags = new ArrayList<>();
345
        while (iterator.hasNext()) {
346
            NomenclaturalStatus ncStatus = iterator.next();
347
            // since the NewInstance method of nomencatural status allows null as parameter
348
            // we have to check for null values here
349
            String nomStatusStr = "not defined";
350
            if(ncStatus.getType() != null){
351
                NomenclaturalStatusType statusType =  ncStatus.getType();
352
                Language lang = Language.LATIN();
353
                Representation repr = statusType.getRepresentation(lang);
354
                if (repr != null){
355
                    nomStatusStr = repr.getAbbreviatedLabel();
356
                }else{
357
                    String message = "No latin representation available for nom. status. " + statusType.getTitleCache();
358
                    logger.warn(message);
359
                    throw new IllegalStateException(message);
360
                }
361
            }else if(StringUtils.isNotBlank(ncStatus.getRuleConsidered())){
362
                nomStatusStr = ncStatus.getRuleConsidered();
363
            }
364
            String statusSeparator = ", ";
365
            if (includeSeparatorBefore){
366
                nomStatusTags.add(new TaggedText(TagEnum.separator, statusSeparator));
367
            }
368
            nomStatusTags.add(new TaggedText(TagEnum.nomStatus, nomStatusStr));
369
            if (includeSeparatorAfter){
370
                nomStatusTags.add(new TaggedText(TagEnum.postSeparator, ","));
371
            }
372
        }
373
        return nomStatusTags;
374
    }
375

  
376
    @Override
377
    public List<TaggedText> getTaggedTitle(TaxonName nonViralName) {
378
        if (nonViralName == null){
379
            return null;
380
        }
381

  
382
        List<TaggedText> tags = new ArrayList<>();
383

  
384
        //TODO how to handle protected fullTitleCache here?
385

  
386
        if (nonViralName.isProtectedTitleCache()){
387
            //protected title cache
388
            tags.add(new TaggedText(TagEnum.name, nonViralName.getTitleCache()));
389
            return tags;
390
        }else if (nonViralName.isHybridFormula()){
391
            //hybrid formula
392
            String hybridSeparator = NonViralNameParserImplRegExBase.hybridSign;
393
            boolean isFirst = true;
394
            List<HybridRelationship> rels = nonViralName.getOrderedChildRelationships();
395
            for (HybridRelationship rel: rels){
396
                if (! isFirst){
397
                    tags.add(new TaggedText(TagEnum.hybridSign, hybridSeparator));
398
                }
399
                isFirst = false;
400
                tags.addAll(getTaggedTitle(rel.getParentName()));
401
            }
402
            return tags;
403
        }else if (nonViralName.isAutonym()){
404
            //Autonym
405
            tags.addAll(handleTaggedAutonym(nonViralName));
406
        }else{ //not Autonym
407
//			String nameCache = nonViralName.getNameCache();  //OLD: CdmUtils.Nz(getNameCache(nonViralName));
408

  
409
            List<TaggedText> nameTags = getTaggedName(nonViralName);
410
            tags.addAll(nameTags);
411
            String authorCache = getAuthorshipCache(nonViralName);
412
            if (StringUtils.isNotBlank(authorCache)){
413
                tags.add(new TaggedText(TagEnum.authors, authorCache));
414
            }
415
        }
416

  
417
        return tags;
418
    }
419

  
420
    /**
421
     * Returns the tag list of the name part (without author and reference).
422
     * @param nonViralName
423
     * @return
424
     */
425
    @Override
426
    public List<TaggedText> getTaggedName(TaxonName nonViralName) {
427
        if (nonViralName == null){
428
            return null;
429
        }
430
        List<TaggedText> tags = new ArrayList<>();
431
        Rank rank = nonViralName.getRank();
432

  
433
        if (nonViralName.isProtectedNameCache()){
434
            tags.add(new TaggedText(TagEnum.name, nonViralName.getNameCache()));
435
        }else if (nonViralName.isHybridFormula()){
436
            //hybrid formula
437
            String hybridSeparator = NonViralNameParserImplRegExBase.hybridSign;
438
            boolean isFirst = true;
439
            List<HybridRelationship> rels = nonViralName.getOrderedChildRelationships();
440
            for (HybridRelationship rel: rels){
441
                if (! isFirst){
442
                    tags.add(new TaggedText(TagEnum.hybridSign, hybridSeparator));
443
                }
444
                isFirst = false;
445
                tags.addAll(getTaggedName(rel.getParentName()));
446
            }
447
            return tags;
448

  
449
        }else if (rank == null){
450
            tags = getRanklessTaggedNameCache(nonViralName);
451
//		}else if (nonViralName.isInfragenericUnranked()){
452
//			result = getUnrankedInfragenericNameCache(nonViralName);
453
        }else if (rank.isInfraSpecific()){
454
            tags = getInfraSpeciesTaggedNameCache(nonViralName);
455
        }else if (rank.isSpecies() || isAggregateWithAuthorship(nonViralName, rank) ){ //exception see #4288
456
            tags = getSpeciesTaggedNameCache(nonViralName);
457
        }else if (rank.isInfraGeneric()){
458
            tags = getInfraGenusTaggedNameCache(nonViralName);
459
        }else if (rank.isGenus()){
460
            tags = getGenusOrUninomialTaggedNameCache(nonViralName);
461
        }else if (rank.isSupraGeneric()){
462
            tags = getGenusOrUninomialTaggedNameCache(nonViralName);
463
        }else{
464
            logger.warn("Name Strategy for Name (UUID: " + nonViralName.getUuid() +  ") not yet implemented");
465
        }
466
        //TODO handle appended phrase here instead of different places, check first if this is true for all
467
        //cases
468

  
469
        return tags;
470

  
471
    }
472

  
473

  
474

  
475

  
476
//***************************** PRIVATES ***************************************/
477

  
478

  
479
    private boolean isAggregateWithAuthorship(TaxonName nonViralName, Rank rank) {
480
		if (rank == null){
481
			return false;
482
		}else{
483
			return rank.isSpeciesAggregate() && ( isNotBlank(nonViralName.getAuthorshipCache()) || nonViralName.getNomenclaturalReference() != null );
484
		}
485
	}
486

  
487

  
488
	/**
489
     * Returns the tag list for an autonym taxon.
490
     *
491
     * @see NonViralName#isAutonym()
492
     * @see BotanicalName#isAutonym()
493
     * @param nonViralName
494
     * @return
495
     */
496
    private List<TaggedText> handleTaggedAutonym(TaxonName nonViralName) {
497
    	List<TaggedText> tags = null;
498
    	if (nonViralName.isInfraSpecific()){
499
	        //species part
500
	        tags = getSpeciesTaggedNameCache(nonViralName);
501

  
502
	        //author
503
	        String authorCache = getAuthorshipCache(nonViralName);
504
	        if (StringUtils.isNotBlank(authorCache)){
505
	            tags.add(new TaggedText(TagEnum.authors, authorCache));
506
	        }
507

  
508

  
509
	        //infra species marker
510
	        if (nonViralName.getRank() == null || !nonViralName.getRank().isInfraSpecific()){
511
	            //TODO handle exception
512
	            logger.warn("Rank for autonym does not exist or is not lower than species !!");
513
	        }else{
514
	            String infraSpeciesMarker = nonViralName.getRank().getAbbreviation();
515
	            if (nonViralName.isTrinomHybrid()){
516
	                infraSpeciesMarker = CdmUtils.concat("", NOTHO, infraSpeciesMarker);
517
	            }
518
	            if (StringUtils.isNotBlank(infraSpeciesMarker)){
519
	                tags.add(new TaggedText(TagEnum.rank, infraSpeciesMarker));
520
	            }
521
	        }
522

  
523
	        //infra species
524
	        String infraSpeciesPart = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet()).trim();
525
	        if (StringUtils.isNotBlank(infraSpeciesPart)){
526
	            tags.add(new TaggedText(TagEnum.name, infraSpeciesPart));
527
	        }
528

  
529
        } else if (nonViralName.isInfraGeneric()){
530
        	//genus part
531
	       tags =getGenusOrUninomialTaggedNameCache(nonViralName);
532

  
533

  
534
	        //infra species marker
535
	        if (nonViralName.getRank() == null || !nonViralName.getRank().isInfraGeneric()){
536
	            //TODO handle exception
537
	            logger.warn("Rank for autonym does not exist or is not lower than species !!");
538
	        }else{
539
	        	Rank rank = nonViralName.getRank();
540
	            String infraGenericMarker = rank.getAbbreviation();
541
                if (rank.equals(Rank.SECTION_BOTANY()) || rank.equals(Rank.SUBSECTION_BOTANY())){
542
                	infraGenericMarker = infraGenericMarker.replace("(bot.)", "");
543
                }
544
	            if (StringUtils.isNotBlank(infraGenericMarker)){
545
	                tags.add(new TaggedText(TagEnum.rank, infraGenericMarker));
546
	            }
547
	        }
548

  
549
	        //infra species
550
	        String infraGenericPart = CdmUtils.Nz(nonViralName.getInfraGenericEpithet()).trim();
551
	        if (StringUtils.isNotBlank(infraGenericPart)){
552
	            tags.add(new TaggedText(TagEnum.name, infraGenericPart));
553
	        }
554

  
555
        }
556

  
557
        return tags;
558
    }
559

  
560

  
561

  
562
    /**
563
     * Returns the tag list for rankless taxa.
564
     * @param nonViralName
565
     * @return
566
     */
567
    protected List<TaggedText> getRanklessTaggedNameCache(INonViralName nonViralName){
568
        List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
569
        String speciesEpi = CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim();
570
        if (StringUtils.isNotBlank(speciesEpi)){
571
            tags.add(new TaggedText(TagEnum.name, speciesEpi));
572
        }
573

  
574
        String infraSpeciesEpi = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet());
575
        if (StringUtils.isNotBlank(infraSpeciesEpi)){
576
            tags.add(new TaggedText(TagEnum.name, infraSpeciesEpi));
577
        }
578

  
579
        //result += " (rankless)";
580
        addAppendedTaggedPhrase(tags, nonViralName);
581
        return tags;
582
    }
583

  
584
    /**
585
     * Returns the tag list for the first epithet (including a hybrid sign if required).
586
     * @param nonViralName
587
     * @return
588
     */
589
    private List<TaggedText> getUninomialTaggedPart(INonViralName nonViralName) {
590
        List<TaggedText> tags = new ArrayList<>();
591

  
592
        if (nonViralName.isMonomHybrid()){
593
            addHybridPrefix(tags);
594
        }
595

  
596
        String uninomial = CdmUtils.Nz(nonViralName.getGenusOrUninomial()).trim();
597
        if (StringUtils.isNotBlank(uninomial)){
598
            tags.add(new TaggedText(TagEnum.name, uninomial));
599
        }
600

  
601
        return tags;
602
    }
603

  
604
    /**
605
     * Returns the tag list for an genus or higher taxon.
606
     *
607
     * @param nonViralName
608
     * @return
609
     */
610
    protected List<TaggedText> getGenusOrUninomialTaggedNameCache(INonViralName nonViralName){
611
        List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
612
        addAppendedTaggedPhrase(tags, nonViralName);
613
        return tags;
614
    }
615

  
616
    /**
617
     * Returns the tag list for an infrageneric taxon (including species aggregates).
618
     *
619
     * @see #getSpeciesAggregateTaggedCache(NonViralName)
620
     * @param nonViralName
621
     * @return
622
     */
623
    protected List<TaggedText> getInfraGenusTaggedNameCache(INonViralName nonViralName){
624
        Rank rank = nonViralName.getRank();
625
        if (rank != null && rank.isSpeciesAggregate() && isBlank(nonViralName.getAuthorshipCache())){
626
            return getSpeciesAggregateTaggedCache(nonViralName);
627
        }
628

  
629
        //genus
630
        List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
631

  
632
        //marker
633
        String infraGenericMarker;
634
        if (rank != null){
635
            try {
636
                infraGenericMarker = rank.getInfraGenericMarker();
637
                if (rank.equals(Rank.SECTION_BOTANY()) || rank.equals(Rank.SUBSECTION_BOTANY())){
638
                	infraGenericMarker = infraGenericMarker.replace("(bot.)", "");
639
                }
640
            } catch (UnknownCdmTypeException e) {
641
                infraGenericMarker = "'unhandled infrageneric rank'";
642
            }
643
        }else{
644
        	infraGenericMarker = "'undefined infrageneric rank'";
645
        }
646
        String infraGenEpi = CdmUtils.Nz(nonViralName.getInfraGenericEpithet()).trim();
647
        if (nonViralName.isBinomHybrid()){
648
            infraGenericMarker = CdmUtils.concat("", NOTHO, infraGenericMarker);
649
        }
650

  
651
        addInfraGenericPart(nonViralName, tags, infraGenericMarker, infraGenEpi);
652

  
653
        addAppendedTaggedPhrase(tags, nonViralName);
654
        return tags;
655
    }
656

  
657

  
658
	/**
659
	 * Default implementation for the infrageneric part of a name.
660
	 * This is usually the infrageneric marker and the infrageneric epitheton. But may be
661
	 * implemented differently e.g. for zoological names the infrageneric epitheton
662
	 * may be surrounded by brackets and the marker left out.
663
	 * @param nonViralName
664
	 * @param tags
665
	 * @param infraGenericMarker
666
	 */
667
	protected void addInfraGenericPart(
668
	        @SuppressWarnings("unused") INonViralName name,
669
	        List<TaggedText> tags,
670
	        String infraGenericMarker,
671
	        String infraGenEpi) {
672
		//add marker
673
		tags.add(new TaggedText(TagEnum.rank, infraGenericMarker));
674

  
675
		//add epitheton
676
		if (StringUtils.isNotBlank(infraGenEpi)){
677
            tags.add(new TaggedText(TagEnum.name, infraGenEpi));
678
        }
679
	}
680

  
681
    /**
682
     * Returns the tag list for a species aggregate (or similar) taxon.<BR>
683
     * Possible ranks for a <i>species aggregate</i> are "aggr.", "species group", ...
684
     * @param nonViralName
685
     * @return
686
     */
687
    protected List<TaggedText> getSpeciesAggregateTaggedCache(INonViralName nonViralName){
688
        if (! isBlank(nonViralName.getAuthorshipCache())){
689
        	List<TaggedText> result = getSpeciesTaggedNameCache(nonViralName);
690
        	return result;
691
        }
692

  
693

  
694
    	List<TaggedText> tags = getGenusAndSpeciesTaggedPart(nonViralName);
695

  
696
        addSpeciesAggregateTaggedEpithet(tags, nonViralName);
697
        addAppendedTaggedPhrase(tags, nonViralName);
698
        return tags;
699
    }
700

  
701
    /**
702
     * Adds the aggregate tag to the tag list.
703
     * @param tags
704
     * @param nonViralName
705
     */
706
    private void addSpeciesAggregateTaggedEpithet(List<TaggedText> tags, INonViralName nonViralName) {
707
        String marker;
708
        try {
709
            marker = nonViralName.getRank().getInfraGenericMarker();
710
        } catch (UnknownCdmTypeException e) {
711
            marker = "'unknown aggregat type'";
712
        }
713
        if (StringUtils.isNotBlank(marker)){
714
            tags.add(new TaggedText(TagEnum.rank, marker));
715
        }
716
    }
717

  
718

  
719
    /**
720
     * Returns the tag list for a species taxon.
721
     * @param nonViralName
722
     * @return
723
     */
724
    protected List<TaggedText> getSpeciesTaggedNameCache(INonViralName nonViralName){
725
        List<TaggedText> tags = getGenusAndSpeciesTaggedPart(nonViralName);
726
        addAppendedTaggedPhrase(tags, nonViralName);
727
        return tags;
728
    }
729

  
730
    /**
731
     * Creates the tag list for an infraspecific taxon. In include is true the result will contain
732
     * @param nonViralName
733
     * @return
734
     */
735
    protected List<TaggedText> getInfraSpeciesTaggedNameCache(TaxonName nonViralName){
736
        if (nonViralName.getNameType().isZoological()){
737
            boolean includeMarker = ! (nonViralName.isAutonym());
738
            return getInfraSpeciesTaggedNameCache(nonViralName, includeMarker);
739
        }else{
740
            return getInfraSpeciesTaggedNameCache(nonViralName, true);
741
        }
742
    }
743

  
744
    /**
745
     * Creates the tag list for an infraspecific taxon. If include is true the result will contain
746
     * the infraspecific marker (e.g. "var.")
747
     * @param nonViralName
748
     * @param includeMarker
749
     * @return
750
     */
751
    protected List<TaggedText> getInfraSpeciesTaggedNameCache(INonViralName nonViralName, boolean includeMarker){
752
        List<TaggedText> tags = getGenusAndSpeciesTaggedPart(nonViralName);
753
        if (includeMarker || nonViralName.isTrinomHybrid()){
754
            String marker = (nonViralName.getRank().getAbbreviation()).trim().replace("null", "");
755
            if (nonViralName.isTrinomHybrid()){
756
                marker = CdmUtils.concat("", NOTHO, marker);
757
            }
758
            if (StringUtils.isNotBlank(marker)){
759
                tags.add(new TaggedText(TagEnum.rank, marker));
760
            }
761

  
762
        }
763
        String infrSpecEpi = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet());
764

  
765
        infrSpecEpi = infrSpecEpi.trim().replace("null", "");
766

  
767
        if (StringUtils.isNotBlank(infrSpecEpi)){
768
            tags.add(new TaggedText(TagEnum.name, infrSpecEpi));
769
        }
770

  
771
        addAppendedTaggedPhrase(tags, nonViralName);
772
        return tags;
773
    }
774

  
775

  
776
    /**
777
     * Adds a tag for the hybrid sign and an empty separator to avoid trailing whitespaces.
778
     * @param tags
779
     */
780
    private void addHybridPrefix(List<TaggedText> tags) {
781
        tags.add(new TaggedText(TagEnum.hybridSign, NonViralNameParserImplRegExBase.hybridSign));
782
        tags.add(new TaggedText(TagEnum.separator, "")); //no whitespace separator
783
    }
784

  
785
    /**
786
     * Creates the tag list for the genus and species part.
787
     * @param nonViralName
788
     * @return
789
     */
790
    private List<TaggedText> getGenusAndSpeciesTaggedPart(INonViralName nonViralName) {
791
        //Uninomial
792
        List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
793

  
794
        //InfraGenericEpi
795
        boolean hasInfraGenericEpi = StringUtils.isNotBlank(nonViralName.getInfraGenericEpithet());
796
        if (hasInfraGenericEpi){
797
            String infrGenEpi = nonViralName.getInfraGenericEpithet().trim();
798
            if (nonViralName.isBinomHybrid()){
799
                //maybe not correct but not really expected to happen
800
                infrGenEpi = UTF8.HYBRID + infrGenEpi;
801
            }
802
            infrGenEpi = "(" + infrGenEpi + ")";
803
            tags.add(new TaggedText(TagEnum.name, infrGenEpi));
804
        }
805

  
806
        //Species Epi
807
        String specEpi = CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim();
808
        if (! hasInfraGenericEpi && nonViralName.isBinomHybrid() ||
809
                hasInfraGenericEpi && nonViralName.isTrinomHybrid()){
810
            addHybridPrefix(tags);
811
        }
812
        if (StringUtils.isNotBlank(specEpi)){
813
            tags.add(new TaggedText(TagEnum.name, specEpi));
814
        }
815
        return tags;
816
    }
817

  
818
    /**
819
     * Adds the tag for the appended phrase if an appended phrase exists
820
     * @param tags
821
     * @param nonViralName
822
     */
823
    protected void addAppendedTaggedPhrase(List<TaggedText> tags, INonViralName nonViralName){
824
        String appendedPhrase = nonViralName ==null ? null : nonViralName.getAppendedPhrase();
825
        if (StringUtils.isNotEmpty(appendedPhrase)){
826
            tags.add(new TaggedText(TagEnum.name, appendedPhrase));
827
        }
828
    }
829

  
830

  
831
	@Override
832
    public String getLastEpithet(TaxonName taxonName) {
833
        Rank rank = taxonName.getRank();
834
        if(rank.isGenus() || rank.isSupraGeneric()) {
835
            return taxonName.getGenusOrUninomial();
836
        } else if(rank.isInfraGeneric()) {
837
            return taxonName.getInfraGenericEpithet();
838
        } else if(rank.isSpecies()) {
839
            return taxonName.getSpecificEpithet();
840
        } else {
841
            return taxonName.getInfraSpecificEpithet();
842
        }
843
    }
844

  
845

  
846
    /**
847
     * {@inheritDoc}
848
     */
849
    @Override
850
    protected List<TaggedText> doGetTaggedTitle(TaxonName nonViralName) {
851
        List<TaggedText> tags = new ArrayList<>();
852
        if (nonViralName.isHybridFormula()){
853
            //hybrid formula
854
            String hybridSeparator = NonViralNameParserImplRegExBase.hybridSign;
855
            boolean isFirst = true;
856
            List<HybridRelationship> rels = nonViralName.getOrderedChildRelationships();
857
            for (HybridRelationship rel: rels){
858
                if (! isFirst){
859
                    tags.add(new TaggedText(TagEnum.hybridSign, hybridSeparator));
860
                }
861
                isFirst = false;
862
                tags.addAll(getTaggedTitle(rel.getParentName()));
863
            }
864
            return tags;
865
        }else if (nonViralName.isAutonym()){
866
            //Autonym
867
            tags.addAll(handleTaggedAutonym(nonViralName));
868
        }else{ //not Autonym
869
    //      String nameCache = nonViralName.getNameCache();  //OLD: CdmUtils.Nz(getNameCache(nonViralName));
870

  
871
            List<TaggedText> nameTags = getTaggedName(nonViralName);
872
            tags.addAll(nameTags);
873
            String authorCache = getAuthorshipCache(nonViralName);
874
            if (StringUtils.isNotBlank(authorCache)){
875
                tags.add(new TaggedText(TagEnum.authors, authorCache));
876
            }
877
        }
878
        return tags;
879
    }
880

  
881
}
cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/TaxonNameDefaultCacheStrategy.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.common.UTF8;
22
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
23
import eu.etaxonomy.cdm.model.agent.INomenclaturalAuthor;
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.INonViralName;
28
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
29
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
30
import eu.etaxonomy.cdm.model.name.Rank;
31
import eu.etaxonomy.cdm.model.name.TaxonName;
32
import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
33
import eu.etaxonomy.cdm.model.reference.Reference;
34
import eu.etaxonomy.cdm.strategy.cache.TagEnum;
35
import eu.etaxonomy.cdm.strategy.cache.TaggedText;
36
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
37
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImplRegExBase;
38

  
39

  
40
/**
41
 * This class is a default implementation for the INonViralNameCacheStrategy<T extends NonViralName>
42
 * interface.<BR>
43
 * The method implements a cache strategy for botanical names so no method has to be overwritten by
44
 * a subclass for botanic names.
45
 * Where differing from this default botanic name strategy other subclasses should overwrite the
46
 * existing methods, e.g. a CacheStrategy for zoological names should overwrite getAuthorAndExAuthor
47
 * @author a.mueller
48
 */
49
public class TaxonNameDefaultCacheStrategy
50
        extends NameCacheStrategyBase
51
        implements INonViralNameCacheStrategy {
52

  
53
    private static final Logger logger = Logger.getLogger(TaxonNameDefaultCacheStrategy.class);
54
	private static final long serialVersionUID = -6577757501563212669L;
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
    private static String NOTHO = "notho";
63
    protected CharSequence basionymAuthorCombinationAuthorSeperator = " ";
64

  
65
    protected String zooAuthorYearSeperator = ", ";
66

  
67

  
68

  
69
    @Override
70
    public  UUID getUuid(){
71
        return uuid;
72
    }
73

  
74
// ************************** FACTORY  ******************************/
75

  
76
    public static TaxonNameDefaultCacheStrategy NewInstance(){
77
        return new TaxonNameDefaultCacheStrategy();
78
    }
79

  
80

  
81
// ************ CONSTRUCTOR *******************/
82

  
83
    protected TaxonNameDefaultCacheStrategy(){
84
        super();
85
    }
86

  
87
/* **************** GETTER / SETTER **************************************/
88

  
89
    /**
90
     * String that separates the NameCache part from the AuthorCache part
91
     * @return
92
     */
93
    public String getNameAuthorSeperator() {
94
        return nameAuthorSeperator;
95
    }
96
    public void setNameAuthorSeperator(String nameAuthorSeperator) {
97
        this.nameAuthorSeperator = nameAuthorSeperator;
98
    }
99

  
100

  
101
    /**
102
     * String the basionym author part starts with e.g. '('.
103
     * This should correspond with the {@link TaxonNameDefaultCacheStrategy#getBasionymEnd() basionymEnd} attribute
104
     * @return
105
     */
106
    public String getBasionymStart() {
107
        return basionymStart;
108
    }
109
    public void setBasionymStart(String basionymStart) {
110
        this.basionymStart = basionymStart;
111
    }
112

  
113
    /**
114
     * String the basionym author part ends with e.g. ')'.
115
     * This should correspond with the {@link TaxonNameDefaultCacheStrategy#getBasionymStart() basionymStart} attribute
116
     * @return
117
     */
118
    public String getBasionymEnd() {
119
        return basionymEnd;
120
    }
121
    public void setBasionymEnd(String basionymEnd) {
122
        this.basionymEnd = basionymEnd;
123
    }
124

  
125

  
126
    /**
127
     * String to separate ex author from author.
128
     * @return
129
     */
130
    public String getExAuthorSeperator() {
131
        return exAuthorSeperator;
132
    }
133
    public void setExAuthorSeperator(String exAuthorSeperator) {
134
        this.exAuthorSeperator = exAuthorSeperator;
135
    }
136

  
137

  
138
    /**
139
     * String that separates the basionym/original_combination author part from the combination author part
140
     * @return
141
     */
142
    public CharSequence getBasionymAuthorCombinationAuthorSeperator() {
143
        return basionymAuthorCombinationAuthorSeperator;
144
    }
145

  
146

  
147
    public void setBasionymAuthorCombinationAuthorSeperator( CharSequence basionymAuthorCombinationAuthorSeperator) {
148
        this.basionymAuthorCombinationAuthorSeperator = basionymAuthorCombinationAuthorSeperator;
149
    }
150

  
151
    public String getZooAuthorYearSeperator() {
152
        return zooAuthorYearSeperator;
153
    }
154
    public void setZooAuthorYearSeperator(String authorYearSeperator) {
155
        this.zooAuthorYearSeperator = authorYearSeperator;
156
    }
157

  
158

  
159
//** *****************************************************************************************/
160

  
161

  
162

  
163

  
164
// ******************* Authorship ******************************/
165

  
166
    @Override
167
    public String getAuthorshipCache(TaxonName taxonName) {
168
        if (taxonName == null){
169
            return null;
170
        }else if (taxonName.getNameType().isViral()){
171
            return null;
172
        }else if(taxonName.isProtectedAuthorshipCache() == true) {
173
            //cache protected
174
            return taxonName.getAuthorshipCache();
175
        }else{
176
            return getNonCacheAuthorshipCache(taxonName);
177
        }
178
    }
179

  
180
    /**
181
     * Returns the authorshipcache string for the atomized authorship fields. Does not use the authorship field.
182
     * @throws NullPointerException if nonViralName is null.
183
     * @param taxonName
184
     * @return
185
     */
186
    protected String getNonCacheAuthorshipCache(TaxonName nonViralName){
187
        if (nonViralName.getNameType().isZoological()){
188
            return this.getZoologicalNonCacheAuthorshipCache(nonViralName);
189
        }else{
190
            String result = "";
191
            INomenclaturalAuthor combinationAuthor = nonViralName.getCombinationAuthorship();
192
            INomenclaturalAuthor exCombinationAuthor = nonViralName.getExCombinationAuthorship();
193
            INomenclaturalAuthor basionymAuthor = nonViralName.getBasionymAuthorship();
194
            INomenclaturalAuthor exBasionymAuthor = nonViralName.getExBasionymAuthorship();
195
            String basionymPart = "";
196
            String authorPart = "";
197
            //basionym
198
            if (basionymAuthor != null || exBasionymAuthor != null){
199
                basionymPart = basionymStart + getAuthorAndExAuthor(basionymAuthor, exBasionymAuthor) + basionymEnd;
200
            }
201
            if (combinationAuthor != null || exCombinationAuthor != null){
202
                authorPart = getAuthorAndExAuthor(combinationAuthor, exCombinationAuthor);
203
            }
204
            result = CdmUtils.concat(basionymAuthorCombinationAuthorSeperator, basionymPart, authorPart);
205
//        if ("".equals(result)){
206
//        	result = null;
207
//        }
208
            return result;
209
        }
210
    }
211

  
212
    protected String getZoologicalNonCacheAuthorshipCache(TaxonName nonViralName) {
213
        if (nonViralName == null){
214
            return null;
215
        }
216
        String result = "";
217
        INomenclaturalAuthor combinationAuthor = nonViralName.getCombinationAuthorship();
218
        INomenclaturalAuthor exCombinationAuthor = nonViralName.getExCombinationAuthorship();
219
        INomenclaturalAuthor basionymAuthor = nonViralName.getBasionymAuthorship();
220
        INomenclaturalAuthor exBasionymAuthor = nonViralName.getExBasionymAuthorship();
221
        Integer publicationYear = nonViralName.getPublicationYear();
222
        Integer originalPublicationYear = nonViralName.getOriginalPublicationYear();
223

  
224
        String basionymPart = "";
225
        String authorPart = "";
226
        //basionym
227
        if (basionymAuthor != null || exBasionymAuthor != null || originalPublicationYear != null ){
228
            String authorAndEx = getAuthorAndExAuthor(basionymAuthor, exBasionymAuthor);
229
            String originalPublicationYearString = originalPublicationYear == null ? null : String.valueOf(originalPublicationYear);
230
            String authorAndExAndYear = CdmUtils.concat(zooAuthorYearSeperator, authorAndEx, originalPublicationYearString );
231
            basionymPart = basionymStart + authorAndExAndYear + basionymEnd;
232
        }
233
        if (combinationAuthor != null || exCombinationAuthor != null){
234
            String authorAndEx = getAuthorAndExAuthor(combinationAuthor, exCombinationAuthor);
235
            String publicationYearString = publicationYear == null ? null : String.valueOf(publicationYear);
236
            authorPart = CdmUtils.concat(zooAuthorYearSeperator, authorAndEx, publicationYearString);
237
        }
238
        result = CdmUtils.concat(basionymAuthorCombinationAuthorSeperator, basionymPart, authorPart);
239
        if (result == null){
240
            result = "";
241
        }
242
        return result;
243
    }
244

  
245

  
246
    /**
247
     * Returns the AuthorCache part for a combination of an author and an ex author. This applies on
248
     * combination authors as well as on basionym/orginal combination authors.
249
     * The correct order is exAuthor ex author though some botanist do not know about and do it the
250
     * other way round. (see 46.4-46.6 ICBN (Vienna Code, 2006))
251
     *
252
     * @param author the author
253
     * @param exAuthor the ex-author
254
     * @return
255
     */
256
    protected String getAuthorAndExAuthor(INomenclaturalAuthor author, INomenclaturalAuthor exAuthor){
257
        String authorString = "";
258
        String exAuthorString = "";
259
        if (author != null){
260
            authorString = CdmUtils.Nz(author.getNomenclaturalTitle());
261
        }
262
        if (exAuthor != null){
263
            exAuthorString = CdmUtils.Nz(exAuthor.getNomenclaturalTitle());
264
            exAuthorString += exAuthorSeperator;
265
        }
266
        String result = exAuthorString + authorString;
267
        return result;
268
    }
269

  
270

  
271

  
272
    /**
273
     * Checks if the given name should include the author in it's cached version.<BR>
274
     * This is usually the case but not for <i>species aggregates</i>.
275
     * @param nonViralName
276
     * @return
277
     */
278
    protected boolean nameIncludesAuthorship(INonViralName nonViralName){
279
        Rank rank = nonViralName.getRank();
280
        if (rank != null && rank.isSpeciesAggregate()){
281
            return false;
282
        }else{
283
            return true;
284
        }
285
    }
286

  
287
// ************* TAGGED NAME ***************************************/
288

  
289
    @Override
290
    public List<TaggedText> getTaggedFullTitle(TaxonName nonViralName) {
291
        List<TaggedText> tags = new ArrayList<>();
292

  
293
        //null
294
        if (nonViralName == null){
295
            return null;
296
        }
297

  
298
        //protected full title cache
299
        if (nonViralName.isProtectedFullTitleCache()){
300
            tags.add(new TaggedText(TagEnum.fullName, nonViralName.getFullTitleCache()));
301
            return tags;
302
        }
303

  
304
        //title cache
305
//		String titleCache = nonViralName.getTitleCache();
306
        List<TaggedText> titleTags = getTaggedTitle(nonViralName);
307
        tags.addAll(titleTags);
308

  
309
        //reference
310
        String microReference = nonViralName.getNomenclaturalMicroReference();
311
        INomenclaturalReference ref = nonViralName.getNomenclaturalReference();
312
        String referenceCache = null;
313
        if (ref != null){
314
            Reference reference = HibernateProxyHelper.deproxy(ref, Reference.class);
315
            referenceCache = reference.getNomenclaturalCitation(microReference);
316
        }
317
            //add to tags
318
        if (StringUtils.isNotBlank(referenceCache)){
319
            if (! referenceCache.trim().startsWith("in ")){
320
                String refConcat = ", ";
321
                tags.add(new TaggedText(TagEnum.separator, refConcat));
322
            }
323
            tags.add(new TaggedText(TagEnum.reference, referenceCache));
324
        }
325

  
326
        addOriginalSpelling(tags, nonViralName);
327

  
328
        //nomenclatural status
329
        tags.addAll(getNomStatusTags(nonViralName, true, false));
330
        return tags;
331

  
332
    }
333

  
334

  
335
    /**
336
     * @param nonViralName
337
     * @param tags
338
     * @return
339
     */
340
    @Override
341
    public List<TaggedText> getNomStatusTags(TaxonName nonViralName, boolean includeSeparatorBefore,
342
            boolean includeSeparatorAfter) {
343

  
344
        Set<NomenclaturalStatus> ncStati = nonViralName.getStatus();
345
        Iterator<NomenclaturalStatus> iterator = ncStati.iterator();
346
        List<TaggedText> nomStatusTags = new ArrayList<>();
347
        while (iterator.hasNext()) {
348
            NomenclaturalStatus ncStatus = iterator.next();
349
            // since the NewInstance method of nomencatural status allows null as parameter
350
            // we have to check for null values here
351
            String nomStatusStr = "not defined";
352
            if(ncStatus.getType() != null){
353
                NomenclaturalStatusType statusType =  ncStatus.getType();
354
                Language lang = Language.LATIN();
355
                Representation repr = statusType.getRepresentation(lang);
356
                if (repr != null){
357
                    nomStatusStr = repr.getAbbreviatedLabel();
358
                }else{
359
                    String message = "No latin representation available for nom. status. " + statusType.getTitleCache();
360
                    logger.warn(message);
361
                    throw new IllegalStateException(message);
362
                }
363
            }else if(StringUtils.isNotBlank(ncStatus.getRuleConsidered())){
364
                nomStatusStr = ncStatus.getRuleConsidered();
365
            }
366
            String statusSeparator = ", ";
367
            if (includeSeparatorBefore){
368
                nomStatusTags.add(new TaggedText(TagEnum.separator, statusSeparator));
369
            }
370
            nomStatusTags.add(new TaggedText(TagEnum.nomStatus, nomStatusStr));
371
            if (includeSeparatorAfter){
372
                nomStatusTags.add(new TaggedText(TagEnum.postSeparator, ","));
373
            }
374
        }
375
        return nomStatusTags;
376
    }
377

  
378
    @Override
379
    public List<TaggedText> getTaggedTitle(TaxonName nonViralName) {
380
        if (nonViralName == null){
381
            return null;
382
        }
383

  
384
        List<TaggedText> tags = new ArrayList<>();
385

  
386
        //TODO how to handle protected fullTitleCache here?
387

  
388
        if (nonViralName.isProtectedTitleCache()){
389
            //protected title cache
390
            tags.add(new TaggedText(TagEnum.name, nonViralName.getTitleCache()));
391
            return tags;
392
        }else if (nonViralName.isHybridFormula()){
393
            //hybrid formula
394
            String hybridSeparator = NonViralNameParserImplRegExBase.hybridSign;
395
            boolean isFirst = true;
396
            List<HybridRelationship> rels = nonViralName.getOrderedChildRelationships();
397
            for (HybridRelationship rel: rels){
398
                if (! isFirst){
399
                    tags.add(new TaggedText(TagEnum.hybridSign, hybridSeparator));
400
                }
401
                isFirst = false;
402
                tags.addAll(getTaggedTitle(rel.getParentName()));
403
            }
404
            return tags;
405
        }else if (nonViralName.isAutonym()){
406
            //Autonym
407
            tags.addAll(handleTaggedAutonym(nonViralName));
408
        }else{ //not Autonym
409
            List<TaggedText> nameTags = getTaggedName(nonViralName);
410
            tags.addAll(nameTags);
411
            String authorCache = getAuthorshipCache(nonViralName);
412
            if (StringUtils.isNotBlank(authorCache)){
413
                tags.add(new TaggedText(TagEnum.authors, authorCache));
414
            }
415
        }
416

  
417
        return tags;
418
    }
419

  
420
    /**
421
     * Returns the tag list of the name part (without author and reference).
422
     * @param nonViralName
423
     * @return
424
     */
425
    @Override
426
    public List<TaggedText> getTaggedName(TaxonName nonViralName) {
427
        if (nonViralName == null){
428
            return null;
429
        }else if (nonViralName.getNameType().isViral()){
430
            return null;
431
        }
432
        List<TaggedText> tags = new ArrayList<>();
433
        Rank rank = nonViralName.getRank();
434

  
435
        if (nonViralName.isProtectedNameCache()){
436
            tags.add(new TaggedText(TagEnum.name, nonViralName.getNameCache()));
437
        }else if (nonViralName.isHybridFormula()){
438
            //hybrid formula
439
            String hybridSeparator = NonViralNameParserImplRegExBase.hybridSign;
440
            boolean isFirst = true;
441
            List<HybridRelationship> rels = nonViralName.getOrderedChildRelationships();
442
            for (HybridRelationship rel: rels){
443
                if (! isFirst){
444
                    tags.add(new TaggedText(TagEnum.hybridSign, hybridSeparator));
445
                }
446
                isFirst = false;
447
                tags.addAll(getTaggedName(rel.getParentName()));
448
            }
449
            return tags;
450

  
451
        }else if (rank == null){
452
            tags = getRanklessTaggedNameCache(nonViralName);
453
//		}else if (nonViralName.isInfragenericUnranked()){
454
//			result = getUnrankedInfragenericNameCache(nonViralName);
455
        }else if (rank.isInfraSpecific()){
456
            tags = getInfraSpeciesTaggedNameCache(nonViralName);
457
        }else if (rank.isSpecies() || isAggregateWithAuthorship(nonViralName, rank) ){ //exception see #4288
458
            tags = getSpeciesTaggedNameCache(nonViralName);
459
        }else if (rank.isInfraGeneric()){
460
            tags = getInfraGenusTaggedNameCache(nonViralName);
461
        }else if (rank.isGenus()){
462
            tags = getGenusOrUninomialTaggedNameCache(nonViralName);
463
        }else if (rank.isSupraGeneric()){
464
            tags = getGenusOrUninomialTaggedNameCache(nonViralName);
465
        }else{
466
            logger.warn("Name Strategy for Name (UUID: " + nonViralName.getUuid() +  ") not yet implemented");
467
        }
468
        //TODO handle appended phrase here instead of different places, check first if this is true for all
469
        //cases
470

  
471
        return tags;
472

  
473
    }
474

  
475

  
476

  
477

  
478
//***************************** PRIVATES ***************************************/
479

  
480

  
481
    private boolean isAggregateWithAuthorship(TaxonName nonViralName, Rank rank) {
482
		if (rank == null){
483
			return false;
484
		}else{
485
			return rank.isSpeciesAggregate() && ( isNotBlank(nonViralName.getAuthorshipCache()) || nonViralName.getNomenclaturalReference() != null );
486
		}
487
	}
488

  
489

  
490
	/**
491
     * Returns the tag list for an autonym taxon.
492
     *
493
     * @see NonViralName#isAutonym()
494
     * @see BotanicalName#isAutonym()
495
     * @param nonViralName
496
     * @return
497
     */
498
    private List<TaggedText> handleTaggedAutonym(TaxonName nonViralName) {
499
    	List<TaggedText> tags = null;
500
    	if (nonViralName.isInfraSpecific()){
501
	        //species part
502
	        tags = getSpeciesTaggedNameCache(nonViralName);
503

  
504
	        //author
505
	        String authorCache = getAuthorshipCache(nonViralName);
506
	        if (StringUtils.isNotBlank(authorCache)){
507
	            tags.add(new TaggedText(TagEnum.authors, authorCache));
508
	        }
509

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff