Project

General

Profile

Download (32 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2016 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.reference;
10

    
11
import java.util.List;
12
import java.util.UUID;
13

    
14
import org.apache.commons.lang3.StringUtils;
15
import org.apache.log4j.Logger;
16
import org.joda.time.DateTime;
17
import org.joda.time.format.DateTimeFormat;
18
import org.joda.time.format.DateTimeFormatter;
19

    
20
import eu.etaxonomy.cdm.common.CdmUtils;
21
import eu.etaxonomy.cdm.model.agent.Person;
22
import eu.etaxonomy.cdm.model.agent.Team;
23
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
24
import eu.etaxonomy.cdm.model.common.CdmBase;
25
import eu.etaxonomy.cdm.model.common.VerbatimTimePeriod;
26
import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
27
import eu.etaxonomy.cdm.model.reference.Reference;
28
import eu.etaxonomy.cdm.model.reference.ReferenceType;
29
import eu.etaxonomy.cdm.strategy.StrategyBase;
30
import eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy;
31

    
32
/**
33
 * #5833
34
 * The new single default cache strategy for {@link Reference references}.
35
 * As we do have only one {@link Reference} class left which implements multiple interfaces,
36
 * we may also only need 1 single cache strategy. However, care must be taken as the formatting
37
 * differs dependent on the type an the in-reference structure.
38
 *
39
 * Generally the cache strategy allows to compute 3 formats:<BR>
40
 *
41
 *  1.) for bibliographic references (stored in {@link Reference#getTitleCache() titleCache}).<BR>
42
 *
43
 *  2.) for nomenclatural references (stored in {@link Reference#getAbbrevTitleCache() abbrevTitleCache}),
44
 *      but without micro reference (detail).<BR>
45
 *
46
 *  3.) for nomenclatural references with micro reference, but not stored anywhere as the micro reference
47
 *      is part of the name, not of the reference<BR>
48
 *
49
 *  4.) for short citation (e.g. Author 2009) as defined in {@link IReferenceCacheStrategy#getCitation(Reference, String)}
50
 *  and {@link IReferenceCacheStrategy#createShortCitation(Reference, String, Boolean)}
51
 *
52
 * @author a.mueller
53
 * @since 25.05.2016
54
 */
55
public class DefaultReferenceCacheStrategy
56
        extends StrategyBase
57
        implements INomenclaturalReferenceCacheStrategy{
58

    
59
    private static final long serialVersionUID = 6773742298840407263L;
60
    private static final Logger logger = Logger.getLogger(DefaultReferenceCacheStrategy.class);
61

    
62
    private final static UUID uuid = UUID.fromString("63e669ca-c6be-4a8a-b157-e391c22580f9");
63

    
64
    //article
65
    public static final String UNDEFINED_JOURNAL = "- undefined journal -";
66
    private static final String afterAuthor = ", ";
67

    
68
    //book
69

    
70

    
71
    //(book?) section
72
    private String afterSectionAuthor = " - ";
73

    
74
    //in reference
75
    private String inSeparator = "in ";
76
    private static final String afterInRefAuthor = ", ";
77

    
78
    //common
79
    private static final String blank = " ";
80
    private static final String beforeYear = ". ";
81
    private static final String beforeMicroReference = ": ";
82
    private static final String afterYear = "";
83

    
84
    private static final boolean trim = true;
85

    
86
// ************************ FACTORY ****************************/
87

    
88
    public static DefaultReferenceCacheStrategy NewInstance(){
89
        return new DefaultReferenceCacheStrategy();
90
    }
91

    
92
// ******************************* Main methods ******************************/
93

    
94
    @Override
95
    protected UUID getUuid() {
96
        return uuid;
97
    }
98

    
99
    @Override
100
    public String getTitleCache(Reference reference) {
101
        if (reference == null){
102
            return null;
103
        }
104
        if (reference.isProtectedTitleCache()){
105
            return reference.getTitleCache();
106
        }
107
        boolean isNotAbbrev = false;
108

    
109
        String result;
110
        ReferenceType type = reference.getType();
111

    
112
        if (isRealInRef(reference)){
113
            result = titleCacheRealInRef(reference, isNotAbbrev);
114
        }else if(isNomRef(type)){
115
            //all Non-InRef NomRefs
116
            result =  getTitleWithoutYearAndAuthor(reference, isNotAbbrev);
117
            result = addPages(result, reference);
118
            result = addYear(result, reference, false);
119
            TeamOrPersonBase<?> team = reference.getAuthorship();
120

    
121
            if (type == ReferenceType.Article){
122
                result = CdmUtils.concat(" ", reference.getTitle(), result);
123
                if (team != null &&  isNotBlank(team.getTitleCache())){
124
                    String authorSeparator = isNotBlank(reference.getTitle())? afterAuthor : " ";
125
                    result = team.getTitleCache() + authorSeparator + result;
126
                }
127
            }else{  //if Book, CdDvd, flat Generic, Thesis, WebPage
128
                if (team != null){
129
                    String teamTitle = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
130
                            team.getNomenclaturalTitle(), isNotAbbrev, trim);
131
                    if (teamTitle.length() > 0 ){
132
                        String concat = isNotBlank(result) ? afterAuthor : "";
133
                        result = teamTitle + concat + result;
134
                    }
135
                }
136
            }
137
        }else if (type == ReferenceType.Journal){
138
            result = titleCacheJournal(reference, isNotAbbrev);
139
        }else{
140
            result = titleCacheDefaultReference(reference, isNotAbbrev);
141
        }
142
        if (reference.getType() == ReferenceType.WebPage && reference.getUri() != null && !result.contains(reference.getUri().toString())){
143
            //might become UTF8.EN_DASH in future
144
            result = CdmUtils.concat(" - ", result, reference.getUri().toString());
145
        }
146
        if(reference.getAccessed() != null){
147
            //TODO still a bit preliminary, also brackets may change in future
148
            result = result + " [accessed " + getAccessedString(reference.getAccessed()) +"]";
149
        }
150
        return result;
151
    }
152

    
153
    private String getAccessedString(DateTime accessed) {
154
        DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm");
155
        String result = formatter.print(accessed);
156
        if (result.endsWith(" 00:00")){
157
            result = result.replace(" 00:00", "");
158
        }
159
        return result;
160
    }
161

    
162
    private String addPages(String result, Reference reference) {
163
        //pages
164
        if (isNotBlank(reference.getPages())){
165
            //Removing trailing added just in case, maybe not necessary
166
            result = RemoveTrailingDot(Nz(result)).trim() + ": " + reference.getPages();
167
        }
168
        return result;
169
    }
170

    
171
    private static String RemoveTrailingDot(String str) {
172
        if (str != null && str.endsWith(".")){
173
            str = str.substring(0, str.length()-1);
174
        }
175
        return str;
176
    }
177

    
178
    @Override
179
    public String getFullAbbrevTitleString(Reference reference) {
180
        if (reference == null){
181
            return null;
182
        }
183
        String result;
184
        ReferenceType type = reference.getType();
185
        boolean isAbbrev = true;
186

    
187
        if (reference.isProtectedAbbrevTitleCache()){
188
            return reference.getAbbrevTitleCache();
189
        }
190

    
191
        if (type == ReferenceType.Article){
192
            result =  getTitleWithoutYearAndAuthor(reference, isAbbrev);
193
            boolean useFullDatePublished = false;
194
            result = addYear(result, reference, useFullDatePublished);
195
            TeamOrPersonBase<?> team = reference.getAuthorship();
196
            String articleTitle = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
197
                    reference.getAbbrevTitle(), isAbbrev, trim);
198
            result = CdmUtils.concat(" ", articleTitle, result);  //Article should maybe left out for nomenclatural references (?)
199
            if (team != null &&  isNotBlank(team.getNomenclaturalTitle())){
200
                String authorSeparator = isNotBlank(articleTitle) ? afterAuthor : " ";
201
                result = team.getNomenclaturalTitle() + authorSeparator + result;
202
            }
203
        }else if (isRealInRef(reference)){
204
            result = titleCacheRealInRef(reference, isAbbrev);
205
        }else if (isNomRef(type)){
206
            //FIXME same as titleCache => try to merge, but note article case
207
            result =  getTitleWithoutYearAndAuthor(reference, isAbbrev);
208
            boolean useFullDatePublished = false;
209
            result = addYear(result, reference, useFullDatePublished);
210
            TeamOrPersonBase<?> team = reference.getAuthorship();
211

    
212
            if (team != null){
213
                String teamTitle = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
214
                        team.getNomenclaturalTitle(), isAbbrev, trim);
215
                if (teamTitle.length() > 0 ){
216
                    String concat = isNotBlank(result) ? afterAuthor : "";
217
                    result = teamTitle + concat + result;
218
                }
219
            }
220
        }else if(type == ReferenceType.Journal){
221
            result = titleCacheJournal(reference, isAbbrev);
222
        }else{
223
            result = titleCacheDefaultReference(reference, isAbbrev);
224
        }
225

    
226
        return result;
227
    }
228

    
229
    //TODO see comment on createShortCitation(...)
230
    @Override
231
    public String getCitation(Reference reference, String microReference) {
232
        // mostly copied from nomRefCacheStrat, refCache, journalCache
233

    
234
        if (reference == null){
235
            return null;
236
        }
237
        StringBuilder result = new StringBuilder();
238
        TeamOrPersonBase<?> team = reference.getAuthorship();
239

    
240
        String nextConcat = "";
241

    
242
        if (team != null &&  isNotBlank(team.getTitleCache())){
243
            result.append(team.getTitleCache() );
244
            //here is the difference between nomRef and others
245
            if (isNomRef(reference.getType())) {
246
                nextConcat = afterAuthor;
247
            }else{
248
                //FIXME check if this really makes sense
249
                result.append(afterAuthor);
250
                nextConcat = beforeYear;
251
            }
252
        }
253

    
254
        String year = reference.getYear();
255
        if (isNotBlank(year)){
256
            result.append(nextConcat + year);
257
        }
258
        if (isNotBlank(microReference)){
259
            result.append(": " + microReference);
260
        }
261

    
262
        return result.toString();
263
    }
264

    
265
    @Override
266
    public String createShortCitation(Reference reference, String citationDetail, Boolean withYearBrackets) {
267
        if (withYearBrackets == null){
268
            withYearBrackets = false;
269
        }
270
        if(reference.isProtectedTitleCache()){
271
            return handleCitationDetailInTitleCache(reference.getTitleCache(), citationDetail);
272
        }
273
        TeamOrPersonBase<?> authorship = reference.getAuthorship();
274
        String shortCitation = "";
275
        if (authorship == null) {
276
            return handleCitationDetailInTitleCache(reference.getTitleCache(), citationDetail);
277
        }
278
        authorship = CdmBase.deproxy(authorship);
279
        if (authorship instanceof Person){
280
            shortCitation = getPersonString((Person)authorship);
281
        }
282
        else if (authorship instanceof Team){
283

    
284
            Team team = CdmBase.deproxy(authorship, Team.class);
285
            if (team.isProtectedTitleCache()){
286
                shortCitation = team.getTitleCache();
287
            }else{
288
                List<Person> teamMembers = team.getTeamMembers();
289
                int etAlPosition = 2;
290
                for (int i = 1; i <= teamMembers.size() && i <= etAlPosition; i++){
291
                    Person teamMember = teamMembers.get(i-1);
292
                    if(teamMember == null){
293
                        // this can happen in UIs in the process of adding new members
294
                        continue;
295
                    }
296
                    String concat = TeamDefaultCacheStrategy.concatString(team, teamMembers, i);
297
                    shortCitation += concat + getPersonString(teamMember);
298
                }
299
                if (teamMembers.size() == 0){
300
                    shortCitation = TeamDefaultCacheStrategy.EMPTY_TEAM;
301
                } else if (team.isHasMoreMembers() || teamMembers.size() > etAlPosition){
302
                    shortCitation += TeamDefaultCacheStrategy.ET_AL_TEAM_CONCATINATION_FULL + "al.";
303
                }
304
            }
305
        }
306
        shortCitation = CdmUtils.concat(" ", shortCitation, getShortCitationDate(reference, withYearBrackets, citationDetail));
307

    
308
        return shortCitation;
309
    }
310

    
311
    /**
312
     * Adds the citationDetail to the titleCache string that is returned from a method as data is not
313
     * accurately parsed.
314
     * @return
315
     */
316
    private String handleCitationDetailInTitleCache(String titleCache, String citationDetail) {
317
        if (StringUtils.isBlank(citationDetail)){
318
            return titleCache;
319
        }else if (StringUtils.isBlank(titleCache)){
320
            return ": " + citationDetail;
321
        }else if (citationDetail.length() <= 3){
322
            if (titleCache.contains(": " + citationDetail)){
323
                return titleCache;
324
            }
325
        }else{
326
            if (titleCache.contains(citationDetail)){
327
                return titleCache;
328
            }
329
        }
330
        return titleCache + ": " + citationDetail;
331
    }
332

    
333
    private String getShortCitationDate(Reference reference, boolean withBrackets, String citationDetail) {
334
        String result = null;
335
        if (reference.getDatePublished() != null && !reference.getDatePublished().isEmpty()) {
336
            if (isNotBlank(reference.getDatePublished().getFreeText())){
337
                result = reference.getDatePublished().getFreeText();
338
            }else if (isNotBlank(reference.getYear()) ){
339
                result = reference.getYear();
340
            }
341
            if (StringUtils.isNotEmpty(citationDetail)){
342
                result = CdmUtils.Nz(result) + ": " + citationDetail;
343
            }
344
            if (StringUtils.isNotBlank(result) && withBrackets){
345
                result = "(" + result + ")";
346
            }
347
        }else if (reference.getInReference() != null){
348
            result = getShortCitationDate(reference.getInReference(), withBrackets, citationDetail);
349
        }
350
        return result;
351
    }
352

    
353
    private String getPersonString(Person person) {
354
        String shortCitation;
355
        shortCitation = person.getFamilyName();
356
        if (isBlank(shortCitation) ){
357
            shortCitation = person.getTitleCache();
358
        }
359
        return shortCitation;
360
    }
361

    
362
    @Override
363
    public String getNomenclaturalCache(Reference reference) {
364
        return this.getNomenclaturalCitation(reference, null);
365
    }
366

    
367
// ************************ TITLE CACHE SUBS ********************************************/
368

    
369
    private String titleCacheRealInRef(Reference reference, boolean isAbbrev) {
370
        ReferenceType type = reference.getType();
371
        Reference inRef = reference.getInReference();
372
        boolean hasInRef = (inRef != null);
373

    
374
        String result;
375
        //copy from InRefDefaultCacheStrategyBase
376
        if (inRef != null){
377
            result = CdmUtils.getPreferredNonEmptyString(inRef.getTitleCache(),
378
                    inRef.getAbbrevTitleCache(), isAbbrev, trim)  ;
379
        }else{
380
            result = String.format("- undefined %s -", getUndefinedLabel(type));
381
        }
382

    
383
        //in
384
        result = inSeparator +  result;
385

    
386
        //section title
387
        String title = CdmUtils.getPreferredNonEmptyString(
388
                reference.getTitle(), reference.getAbbrevTitle(), isAbbrev, trim);
389
        if (title.length() > 0){
390
            result = title + blank + result;
391
        }
392

    
393
        //section author
394
        TeamOrPersonBase<?> thisRefTeam = reference.getAuthorship();
395
        String thisRefAuthor = "";
396
        if (thisRefTeam != null){
397
            thisRefAuthor = CdmUtils.getPreferredNonEmptyString(thisRefTeam.getTitleCache(),
398
                    thisRefTeam.getNomenclaturalTitle(), isAbbrev, trim);
399
        }
400
        result = CdmUtils.concat(afterSectionAuthor, thisRefAuthor, result);
401

    
402
        //date
403
        if (reference.getDatePublished() != null && ! reference.getDatePublished().isEmpty()){
404
            String thisRefDate = reference.getDatePublished().toString();
405
            if (hasInRef && reference.getInBook().getDatePublished() != null){
406
                VerbatimTimePeriod inRefDate = reference.getInReference().getDatePublished();
407
                String inRefDateString = inRefDate.getYear();
408
                if (isNotBlank(inRefDateString)){
409
                    int pos = StringUtils.lastIndexOf(result, inRefDateString);
410
                    if (pos > -1 ){
411
                        result = result.substring(0, pos) + thisRefDate + result.substring(pos + inRefDateString.length());
412
                    }else{
413
                        logger.warn("InRefDateString (" + inRefDateString + ") could not be found in result (" + result +")");
414
                    }
415
                }else{
416
                    //avoid duplicate dots ('..')
417
                    String bYearSeparator = result.substring(result.length() -1).equals(beforeYear.substring(0, 1)) ? beforeYear.substring(1) : beforeYear;
418
                    result = result + bYearSeparator + thisRefDate + afterYear;
419
                }
420
            }else{
421
                result = result + beforeYear + thisRefDate + afterYear;
422
            }
423
        }
424
        return result;
425
    }
426

    
427
    private String titleCacheJournal(Reference reference, boolean isAbbrev) {
428
        String result;
429
        //copied from Journal
430

    
431
        //title
432
        result = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
433
                reference.getAbbrevTitle(), isAbbrev, trim);
434

    
435
//          //delete .
436
//          while (result.endsWith(".")){
437
//              result = result.substring(0, result.length()-1);
438
//          }
439
//          result = addYear(result, journal);
440

    
441
        TeamOrPersonBase<?> team = reference.getAuthorship();
442
        if (team != null){
443
            String author = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
444
                    team.getNomenclaturalTitle(), isAbbrev, trim);
445
            if (isNotBlank(author)){
446
                result = author + afterAuthor + result;
447
            }
448
        }
449
        return result;
450
    }
451

    
452
    private String titleCacheDefaultReference(Reference reference, boolean isAbbrev) {
453
        String result;
454
        //copied from ReferenceDefaultCacheStrategy
455
        result = "";
456
        String titel = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
457
                reference.getAbbrevTitle(), isAbbrev, trim);
458
        if (isNotBlank(titel)){
459
            result = titel + blank;
460
        }
461
        //delete .
462
        while (result.endsWith(".")){
463
            result = result.substring(0, result.length()-1);
464
        }
465

    
466
        result = addYearReferenceDefault(result, reference);
467
        TeamOrPersonBase<?> team = reference.getAuthorship();
468
        if (team != null){
469
            String author = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
470
                    team.getNomenclaturalTitle(), isAbbrev, trim);
471
            if (isNotBlank(author)){
472
                result = author + afterAuthor + result;
473
            }
474
        }
475
        return result;
476
    }
477

    
478
// ******************************* HELPER *****************************************/
479

    
480
    @Override
481
    public String getBeforeMicroReference(){
482
        return beforeMicroReference;
483
    }
484

    
485
    private String addYear(String string, Reference nomRef, boolean useFullDatePublished){
486
        String result;
487
        if (string == null){
488
            return null;
489
        }
490
        String year = useFullDatePublished ? nomRef.getDatePublishedString() : nomRef.getYear();
491
        if (isBlank(year)){
492
            result = string + afterYear;
493
        }else{
494
            String concat = isBlank(string)  ? "" : string.endsWith(".")  ? " " : beforeYear;
495
            result = string + concat + year + afterYear;
496
        }
497
        return result;
498
    }
499

    
500
    private String getTitleWithoutYearAndAuthor(Reference ref, boolean isAbbrev){
501
        return TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthor(ref, isAbbrev);
502
    }
503
    private String getTitleWithoutYearAndAuthorGeneric(Reference ref, boolean isAbbrev){
504
        return TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthorGeneric(ref, isAbbrev);
505
    }
506

    
507
    private Object getUndefinedLabel(ReferenceType type) {
508
        if (type == ReferenceType.BookSection){
509
            return "book";
510
        }else if (type == ReferenceType.Generic){
511
            return "generic reference";
512
        }else if (type == ReferenceType.Section){
513
            return "in reference";
514
        } else {
515
            return type.getLabel();
516
        }
517
    }
518

    
519
    /**
520
     * Returns <code>true</code> if the type of the reference originally corresponded to a cache strategy
521
     * which inherited from {@link InRefDefaultCacheStrategyBase} and in case of type {@link ReferenceType#Generic}
522
     * if it really has an inreference (reference.getInreference() != null).
523
     * @param reference
524
     */
525
    private boolean isRealInRef(Reference reference) {
526
        ReferenceType type = (reference.getType());
527
        if (type == null){
528
            return false;
529
        }else if (type == ReferenceType.BookSection || type == ReferenceType.Section){
530
            return true;
531
        }else if (type == ReferenceType.Generic){
532
            return reference.getInReference() != null;
533
        }else{
534
            return false;
535
        }
536
    }
537

    
538
    /**
539
     * Returns <code>true</code> if the type of the reference originally corresponded to a cache strategy
540
     * which inherited from {@link NomRefDefaultCacheStrategyBase}.
541
     * @param type
542
     */
543
    protected static boolean isNomRef(ReferenceType type){
544
        switch (type){
545
            case Article:
546
            case Book:
547
            case BookSection:
548
            case CdDvd:
549
            case Generic:
550
            case Section:
551
            case Thesis:
552
            case WebPage:
553
                return true;
554

    
555
            case Journal:
556
            default:
557
                return false;
558
        }
559
    }
560

    
561
    /**
562
     * Returns year information as originally computed by {@link ReferenceDefaultCacheStrategy}.
563
     */
564
    private String addYearReferenceDefault(String string, Reference ref){
565
        String result;
566
        if (string == null){
567
            return null;
568
        }
569
        String year = CdmUtils.Nz(ref.getYear());
570
        if ("".equals(year)){
571
            result = string + afterYear;
572
        }else{
573
            result = string.trim() + beforeYear + year + afterYear;
574
        }
575
        return result;
576
    }
577

    
578
// ********************* Nomenclatural title ***************************************/
579

    
580
    @Override
581
    public String getNomenclaturalCitation(Reference reference, String microReference) {
582
        if (reference.isProtectedAbbrevTitleCache()){
583
            String cache = reference.getAbbrevTitleCache();
584
            return handleDetailAndYearForProtected(reference, cache, microReference);
585
        }
586

    
587
        String result = getTokenizedNomenclaturalTitel(reference);
588
        //if no data is available and only titleCache is protected take the protected title
589
        //this is to avoid empty cache if someone forgets to set also the abbrevTitleCache
590
        //we need to think about handling protected not separate for abbrevTitleCache  and titleCache
591
        if (result.equals(INomenclaturalReference.MICRO_REFERENCE_TOKEN) && reference.isProtectedTitleCache() ){
592
            String cache = reference.getTitleCache();
593
            return handleDetailAndYearForProtected(reference, cache, microReference);
594
        }
595

    
596
        microReference = Nz(microReference);
597
        if (isNotBlank(microReference)){
598
            microReference = getBeforeMicroReference() + microReference;
599
            if (microReference.endsWith(".")  && result.contains(INomenclaturalReference.MICRO_REFERENCE_TOKEN + ".") ){
600
                microReference = microReference.substring(0, microReference.length() - 1);
601
            }
602
        }
603
        result = replaceMicroRefToken(microReference, result);
604
        if (result.startsWith(". ")){  //only year available, remove '. '
605
            result = result.substring(2);
606
        }
607
        return result;
608
    }
609

    
610
    private String handleDetailAndYearForProtected(Reference nomenclaturalReference, String cache, String microReference) {
611
        String microRef = isNotBlank(microReference) ? getBeforeMicroReference() + microReference : "";
612
        if (cache == null){
613
            logger.warn("Cache is null. This should never be the case.");
614
            cache = "";
615
        }
616
        String  result = cache + (cache.contains(microRef) ? "" : microRef);
617

    
618
        String date = nomenclaturalReference.getDatePublishedString();
619
        if (isNotBlank(date) && ! result.contains(date)){
620
            result = result + beforeYear + date;
621
        }
622
        return result;
623
    }
624

    
625
    /**
626
     * Returns the nomenclatural title with micro reference represented as token
627
     * which can later be replaced by the real data.
628
     *
629
     * @see INomenclaturalReference#MICRO_REFERENCE_TOKEN
630
     */
631
    private String getTokenizedNomenclaturalTitel(Reference ref) {
632
        if (isRealInRef(ref)){
633
            return getTokenizedNomenclaturalTitelInRef(ref);
634
        }else{
635
            String result = getTitleWithoutYearAndAuthor(ref, true);
636
            result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
637
            result = addYear(result, ref, true);
638
            return result;
639
        }
640
    }
641

    
642
    private String getTokenizedNomenclaturalTitelInRef(Reference thisRef) {
643
        if (thisRef == null){
644
            return null;
645
        }
646

    
647
        Reference inRef = CdmBase.deproxy(thisRef.getInReference(), Reference.class);
648
        if (inRef != null && inRef.getInReference() != null && thisRef.getType() == ReferenceType.Section){
649
            //this is a reference of type Section which has a in-in-Ref
650
            //TODO maybe we do not need to restrict to type=Section only
651
            return this.getTokenizedNomenclaturalTitelInInRef(thisRef);
652
        }
653

    
654
        String result;
655
        //use generics's publication date if it exists
656
        if (inRef == null ||  (thisRef.hasDatePublished() ) ){
657
            result =  inRef == null ? "" : getTitleWithoutYearAndAuthorGeneric(inRef, true);
658
            //added //TODO unify with non-inRef references formatting
659

    
660
            if (isNotBlank(thisRef.getVolume())){
661
                result = result + " " + thisRef.getVolume();
662
            }
663
            //TODO series / edition
664

    
665
            //end added
666
            result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
667
            result = addYear(result, thisRef, true);
668
        }else{
669
            //else use inRefs's publication date
670
            result = inRef.getNomenclaturalCitation(INomenclaturalReference.MICRO_REFERENCE_TOKEN);
671
            if (result != null){
672
                result = result.replace(beforeMicroReference +  INomenclaturalReference.MICRO_REFERENCE_TOKEN, INomenclaturalReference.MICRO_REFERENCE_TOKEN);
673
            }
674
        }
675
        //FIXME: vol. etc., https://dev.e-taxonomy.eu/redmine/issues/2862
676

    
677
        result = getInRefAuthorPart(thisRef.getInReference(), afterInRefAuthor) + result;
678
        result = "in " +  result;
679
        return result;
680
    }
681

    
682
    /**
683
     * For handling in-in-Ref case.
684
     * Must only be called if a reference has inRef and inInRef
685
     * @param section
686
     * @return
687
     */
688
    private String getTokenizedNomenclaturalTitelInInRef(Reference ref) {
689
        String result;
690

    
691
        Reference inRef = CdmBase.deproxy(ref.getInReference(), Reference.class);
692
        Reference inInRef = CdmBase.deproxy(inRef.getInReference(), Reference.class);
693

    
694
        if (! isNomRef(inInRef.getType())){
695
            if (! isNomRef(inRef.getType())){
696
                logger.warn("Neither inReference nor inInReference is a "
697
                        + " nomenclatural reference. This is not correct or not handled yet."
698
                        + " Generic titleWithoutYearAndAuthor used instead");
699
                result = getTitleWithoutYearAndAuthorGeneric(inInRef, true);
700
                //FIXME: vol. etc., https://dev.e-taxonomy.eu/redmine/issues/2862  (comment taken from super.getTokenizedNomenclaturalTitel())
701
            }else{
702
                result = getTitleWithoutYearAndAuthor(inRef, true);
703
            }
704
        }else{
705
            result = getTitleWithoutYearAndAuthor(inInRef, true);
706
        }
707
        result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
708

    
709
        Reference dataReference = (ref.hasDatePublished() ? ref : inRef.hasDatePublished() ? inRef : inInRef);
710

    
711
        result = addYear(result, dataReference, true);
712

    
713
        result = getInRefAuthorPart(inInRef, afterInRefAuthor) + result;
714
        if (! result.startsWith("in ")){
715
            result = "in " +  result;
716
        }
717
        return result;
718
    }
719

    
720
    /**
721
     * See https://dev.e-taxonomy.eu/redmine/issues/8881
722
     */
723
    private String getInRefAuthorPart(Reference book, String seperator){
724
        if (book == null){
725
            return "";
726
        }
727

    
728
        TeamOrPersonBase<?> author = book.getAuthorship();
729
        String result;
730
        if (author == null){
731
            result = "";
732
        }else if(author.isInstanceOf(Person.class)){
733
            Person person = CdmBase.deproxy(author, Person.class);
734
            result = getInRefPerson(person);
735
        }else{
736
            Team team = CdmBase.deproxy(author, Team.class);
737
            if (team.isProtectedNomenclaturalTitleCache()){
738
                //not yet finally discussed may change in future
739
                result = team.getNomenclaturalTitle();
740
            }else if (team.isProtectedTitleCache()){
741
                //not yet finally discussed may change in future
742
                result = team.getTitleCache();
743
            }else if (team.getTeamMembers().isEmpty()){
744
                //not yet finally discussed may change in future
745
                result = team.getTitleCache();
746
            }else{
747
                result = "";
748
                int size = team.getTeamMembers().size();
749
                for (Person person : team.getTeamMembers()){
750
                    int index = team.getTeamMembers().lastIndexOf(person);
751
                    String sep = (team.isHasMoreMembers() || index != size - 1) ?
752
                            TeamDefaultCacheStrategy.STD_TEAM_CONCATINATION : TeamDefaultCacheStrategy.FINAL_TEAM_CONCATINATION;
753
                    result = CdmUtils.concat(sep, result, getInRefPerson(person));
754
                }
755
                if (team.isHasMoreMembers()){
756
                    result += TeamDefaultCacheStrategy.ET_AL_TEAM_CONCATINATION_FULL + "al.";
757
                }
758
            }
759
        }
760

    
761
        result = Nz(result);
762
        if (! result.trim().equals("")){
763
            result = result + seperator;
764
        }
765
        return result;
766
    }
767

    
768
    private String getInRefPerson(Person person) {
769
        String result;
770
        if (isNotBlank(person.getFamilyName())){
771
            result = person.getFamilyName();
772
        }else if (isNotBlank(person.getNomenclaturalTitle())){
773
            result = person.getNomenclaturalTitle();  //TODO discuss if nomTitle is really better here then titleCache
774
        }else{
775
            result = person.getTitleCache();  //maybe remove everything behind a ","
776
        }
777
        return result;
778
    }
779

    
780
    private String replaceMicroRefToken(String microReference, String string) {
781
        int index = string.indexOf(INomenclaturalReference.MICRO_REFERENCE_TOKEN);
782

    
783
        if (index > -1){
784
            String before = string.substring(0, index);
785
            String after = string.substring(index + INomenclaturalReference.MICRO_REFERENCE_TOKEN.length() );
786
            String localMicroReference = microReference.trim();   //needed ?
787
            if (after.length() > 0){
788
                if (  ("".equals(localMicroReference) && before.endsWith(after.substring(0,1)) || localMicroReference.endsWith(after.substring(0,1)))){
789
                    after = after.substring(1);
790
                }
791
            }
792
            String result = before + localMicroReference + after;
793
            return result;
794
        }else{
795
            return string;
796
        }
797
    }
798

    
799
// *************************** EXTERNAL USE *******************************************/
800

    
801
   public static String putAuthorToEndOfString(String referenceTitleCache, String authorTitleCache) {
802
       if(authorTitleCache != null){
803
           referenceTitleCache = referenceTitleCache.replace(authorTitleCache + ", ", "");
804
           referenceTitleCache += " - " + authorTitleCache;
805
       }
806
       return referenceTitleCache;
807
   }
808
}
(1-1/4)