Project

General

Profile

Download (30 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.hibernate.HibernateProxyHelper;
22
import eu.etaxonomy.cdm.model.agent.Person;
23
import eu.etaxonomy.cdm.model.agent.Team;
24
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
25
import eu.etaxonomy.cdm.model.common.CdmBase;
26
import eu.etaxonomy.cdm.model.common.VerbatimTimePeriod;
27
import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
28
import eu.etaxonomy.cdm.model.reference.Reference;
29
import eu.etaxonomy.cdm.model.reference.ReferenceType;
30
import eu.etaxonomy.cdm.strategy.StrategyBase;
31
import eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy;
32

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

    
58
    private static final Logger logger = Logger.getLogger(DefaultReferenceCacheStrategy.class);
59

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

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

    
66
    //book
67

    
68

    
69
    //(book?) section
70
    private String afterSectionAuthor = " - ";
71

    
72
    //in reference
73
    private String inSeparator = "in ";
74
    private static final String afterInRefAuthor = ", ";
75

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

    
82
    private static final boolean trim = true;
83

    
84
// ************************ FACTORY ****************************/
85

    
86
    public static DefaultReferenceCacheStrategy NewInstance(){
87
        return new DefaultReferenceCacheStrategy();
88
    }
89

    
90
// ******************************* Main methods ******************************/
91

    
92
    @Override
93
    protected UUID getUuid() {
94
        return uuid;
95
    }
96

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

    
107
        String result;
108
        ReferenceType type = reference.getType();
109

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

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

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

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

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

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

    
185
        if (reference.isProtectedAbbrevTitleCache()){
186
            return reference.getAbbrevTitleCache();
187
        }
188

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

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

    
224
        return result;
225
    }
226

    
227
    @Override
228
    public String getCitation(Reference reference) {
229
        // mostly copied from nomRefCacheStrat, refCache, journalCache
230

    
231
        if (reference == null){
232
            return null;
233
        }
234
        StringBuilder stringBuilder = new StringBuilder();
235
        TeamOrPersonBase<?> team = reference.getAuthorship();
236

    
237
        String nextConcat = "";
238

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

    
251
        String year = reference.getYear();
252
        if (isNotBlank(year)){
253
            stringBuilder.append(nextConcat + year);
254
        }
255

    
256
        return stringBuilder.toString();
257
    }
258

    
259
    public String createShortCitation(Reference reference) {
260
        TeamOrPersonBase<?> authorship = reference.getAuthorship();
261
        String shortCitation = "";
262
        if (authorship == null) {
263
            return null;
264
        }
265
        authorship = HibernateProxyHelper.deproxy(authorship);
266
        if (authorship instanceof Person){
267
            shortCitation = ((Person)authorship).getFamilyName();
268
            if (isBlank(shortCitation) ){
269
                shortCitation = ((Person)authorship).getTitleCache();
270
            }
271
        }
272
        else if (authorship instanceof Team){
273

    
274
            Team authorTeam = HibernateProxyHelper.deproxy(authorship, Team.class);
275
            int index = 0;
276

    
277
            for (Person teamMember : authorTeam.getTeamMembers()){
278
                index++;
279
                if (index == 3){
280
                    shortCitation += " & al.";
281
                    break;
282
                }
283
                String concat = concatString(authorTeam, authorTeam.getTeamMembers(), index, ", ", " & ");
284
                if (teamMember.getFamilyName() != null){
285
                    shortCitation += concat + teamMember.getFamilyName();
286
                }else{
287
                    shortCitation += concat + teamMember.getTitleCache();
288
                }
289

    
290
            }
291
            if (isBlank(shortCitation)){
292
                shortCitation = authorTeam.getTitleCache();
293
            }
294

    
295
        }
296
        if (reference.getDatePublished() != null) {
297
            if (isNotBlank(reference.getDatePublished().getFreeText())){
298
                shortCitation = shortCitation + " (" + reference.getDatePublished().getFreeText() + ")";
299
            }else if (isNotBlank(reference.getYear()) ){
300
                shortCitation = shortCitation + " (" + reference.getYear() + ")";
301
            }
302
        }
303

    
304
        return shortCitation;
305
    }
306

    
307
    private static String concatString(Team team, List<Person> teamMembers, int i, String std_team_concatination, String final_team_concatination) {
308
        String concat;
309
        if (i <= 1){
310
            concat = "";
311
        }else if (i < teamMembers.size() || ( team.isHasMoreMembers() && i == teamMembers.size())){
312
            concat = std_team_concatination;
313
        }else{
314
            concat = final_team_concatination;
315
        }
316
        return concat;
317
    }
318

    
319
    @Override
320
    public String getNomenclaturalCache(Reference reference) {
321
        return this.getNomenclaturalCitation(reference, null);
322
    }
323

    
324
// ************************ TITLE CACHE SUBS ********************************************/
325

    
326
    private String titleCacheRealInRef(Reference reference, boolean isAbbrev) {
327
        ReferenceType type = reference.getType();
328
        Reference inRef = reference.getInReference();
329
        boolean hasInRef = (inRef != null);
330

    
331
        String result;
332
        //copy from InRefDefaultCacheStrategyBase
333
        if (inRef != null){
334
            result = CdmUtils.getPreferredNonEmptyString(inRef.getTitleCache(),
335
                    inRef.getAbbrevTitleCache(), isAbbrev, trim)  ;
336
        }else{
337
            result = String.format("- undefined %s -", getUndefinedLabel(type));
338
        }
339

    
340
        //in
341
        result = inSeparator +  result;
342

    
343
        //section title
344
        String title = CdmUtils.getPreferredNonEmptyString(
345
                reference.getTitle(), reference.getAbbrevTitle(), isAbbrev, trim);
346
        if (title.length() > 0){
347
            result = title + blank + result;
348
        }
349

    
350
        //section author
351
        TeamOrPersonBase<?> thisRefTeam = reference.getAuthorship();
352
        String thisRefAuthor = "";
353
        if (thisRefTeam != null){
354
            thisRefAuthor = CdmUtils.getPreferredNonEmptyString(thisRefTeam.getTitleCache(),
355
                    thisRefTeam.getNomenclaturalTitle(), isAbbrev, trim);
356
        }
357
        result = CdmUtils.concat(afterSectionAuthor, thisRefAuthor, result);
358

    
359
        //date
360
        if (reference.getDatePublished() != null && ! reference.getDatePublished().isEmpty()){
361
            String thisRefDate = reference.getDatePublished().toString();
362
            if (hasInRef && reference.getInBook().getDatePublished() != null){
363
                VerbatimTimePeriod inRefDate = reference.getInReference().getDatePublished();
364
                String inRefDateString = inRefDate.getYear();
365
                if (isNotBlank(inRefDateString)){
366
                    int pos = StringUtils.lastIndexOf(result, inRefDateString);
367
                    if (pos > -1 ){
368
                        result = result.substring(0, pos) + thisRefDate + result.substring(pos + inRefDateString.length());
369
                    }else{
370
                        logger.warn("InRefDateString (" + inRefDateString + ") could not be found in result (" + result +")");
371
                    }
372
                }else{
373
                    //avoid duplicate dots ('..')
374
                    String bYearSeparator = result.substring(result.length() -1).equals(beforeYear.substring(0, 1)) ? beforeYear.substring(1) : beforeYear;
375
                    result = result + bYearSeparator + thisRefDate + afterYear;
376
                }
377
            }else{
378
                result = result + beforeYear + thisRefDate + afterYear;
379
            }
380
        }
381
        return result;
382
    }
383

    
384
    private String titleCacheJournal(Reference reference, boolean isAbbrev) {
385
        String result;
386
        //copied from Journal
387

    
388
        //title
389
        result = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
390
                reference.getAbbrevTitle(), isAbbrev, trim);
391

    
392
//          //delete .
393
//          while (result.endsWith(".")){
394
//              result = result.substring(0, result.length()-1);
395
//          }
396
//          result = addYear(result, journal);
397

    
398
        TeamOrPersonBase<?> team = reference.getAuthorship();
399
        if (team != null){
400
            String author = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
401
                    team.getNomenclaturalTitle(), isAbbrev, trim);
402
            if (isNotBlank(author)){
403
                result = author + afterAuthor + result;
404
            }
405
        }
406
        return result;
407
    }
408

    
409
    private String titleCacheDefaultReference(Reference reference, boolean isAbbrev) {
410
        String result;
411
        //copied from ReferenceDefaultCacheStrategy
412
        result = "";
413
        String titel = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
414
                reference.getAbbrevTitle(), isAbbrev, trim);
415
        if (isNotBlank(titel)){
416
            result = titel + blank;
417
        }
418
        //delete .
419
        while (result.endsWith(".")){
420
            result = result.substring(0, result.length()-1);
421
        }
422

    
423
        result = addYearReferenceDefault(result, reference);
424
        TeamOrPersonBase<?> team = reference.getAuthorship();
425
        if (team != null){
426
            String author = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
427
                    team.getNomenclaturalTitle(), isAbbrev, trim);
428
            if (isNotBlank(author)){
429
                result = author + afterAuthor + result;
430
            }
431
        }
432
        return result;
433
    }
434

    
435
// ******************************* HELPER *****************************************/
436

    
437
    @Override
438
    public String getBeforeMicroReference(){
439
        return beforeMicroReference;
440
    }
441

    
442
    private String addYear(String string, Reference nomRef, boolean useFullDatePublished){
443
        String result;
444
        if (string == null){
445
            return null;
446
        }
447
        String year = useFullDatePublished ? nomRef.getDatePublishedString() : nomRef.getYear();
448
        if (isBlank(year)){
449
            result = string + afterYear;
450
        }else{
451
            String concat = isBlank(string)  ? "" : string.endsWith(".")  ? " " : beforeYear;
452
            result = string + concat + year + afterYear;
453
        }
454
        return result;
455
    }
456

    
457
    private String getTitleWithoutYearAndAuthor(Reference ref, boolean isAbbrev){
458
        return TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthor(ref, isAbbrev);
459
    }
460
    private String getTitleWithoutYearAndAuthorGeneric(Reference ref, boolean isAbbrev){
461
        return TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthorGeneric(ref, isAbbrev);
462
    }
463

    
464
    private Object getUndefinedLabel(ReferenceType type) {
465
        if (type == ReferenceType.BookSection){
466
            return "book";
467
        }else if (type == ReferenceType.Generic){
468
            return "generic reference";
469
        }else if (type == ReferenceType.Section){
470
            return "in reference";
471
        } else {
472
            return type.getMessage();
473
        }
474
    }
475

    
476
    /**
477
     * Returns <code>true</code> if the type of the reference originally corresponded to a cache strategy
478
     * which inherited from {@link InRefDefaultCacheStrategyBase} and in case of type {@link ReferenceType#Generic}
479
     * if it really has an inreference (reference.getInreference() != null).
480
     * @param reference
481
     */
482
    private boolean isRealInRef(Reference reference) {
483
        ReferenceType type = (reference.getType());
484
        if (type == null){
485
            return false;
486
        }else if (type == ReferenceType.BookSection || type == ReferenceType.Section){
487
            return true;
488
        }else if (type == ReferenceType.Generic){
489
            return reference.getInReference() != null;
490
        }else{
491
            return false;
492
        }
493
    }
494

    
495
    /**
496
     * Returns <code>true</code> if the type of the reference originally corresponded to a cache strategy
497
     * which inherited from {@link NomRefDefaultCacheStrategyBase}.
498
     * @param type
499
     */
500
    protected static boolean isNomRef(ReferenceType type){
501
        switch (type){
502
            case Article:
503
            case Book:
504
            case BookSection:
505
            case CdDvd:
506
            case Generic:
507
            case Section:
508
            case Thesis:
509
            case WebPage:
510
                return true;
511

    
512
            case Journal:
513
            default:
514
                return false;
515
        }
516
    }
517

    
518
    /**
519
     * Returns year information as originally computed by {@link ReferenceDefaultCacheStrategy}.
520
     */
521
    private String addYearReferenceDefault(String string, Reference ref){
522
        String result;
523
        if (string == null){
524
            return null;
525
        }
526
        String year = CdmUtils.Nz(ref.getYear());
527
        if ("".equals(year)){
528
            result = string + afterYear;
529
        }else{
530
            result = string.trim() + beforeYear + year + afterYear;
531
        }
532
        return result;
533
    }
534

    
535
// ********************* Nomenclatural title ***************************************/
536

    
537
    @Override
538
    public String getNomenclaturalCitation(Reference reference, String microReference) {
539
        if (reference.isProtectedAbbrevTitleCache()){
540
            String cache = reference.getAbbrevTitleCache();
541
            return handleDetailAndYearForProtected(reference, cache, microReference);
542
        }
543

    
544
        String result = getTokenizedNomenclaturalTitel(reference);
545
        //if no data is available and only titleCache is protected take the protected title
546
        //this is to avoid empty cache if someone forgets to set also the abbrevTitleCache
547
        //we need to think about handling protected not separate for abbrevTitleCache  and titleCache
548
        if (result.equals(INomenclaturalReference.MICRO_REFERENCE_TOKEN) && reference.isProtectedTitleCache() ){
549
            String cache = reference.getTitleCache();
550
            return handleDetailAndYearForProtected(reference, cache, microReference);
551
        }
552

    
553
        microReference = Nz(microReference);
554
        if (isNotBlank(microReference)){
555
            microReference = getBeforeMicroReference() + microReference;
556
            if (microReference.endsWith(".")  && result.contains(INomenclaturalReference.MICRO_REFERENCE_TOKEN + ".") ){
557
                microReference = microReference.substring(0, microReference.length() - 1);
558
            }
559
        }
560
        result = replaceMicroRefToken(microReference, result);
561
        if (result.startsWith(". ")){  //only year available, remove '. '
562
            result = result.substring(2);
563
        }
564
        return result;
565
    }
566

    
567
    private String handleDetailAndYearForProtected(Reference nomenclaturalReference, String cache, String microReference) {
568
        String microRef = isNotBlank(microReference) ? getBeforeMicroReference() + microReference : "";
569
        if (cache == null){
570
            logger.warn("Cache is null. This should never be the case.");
571
            cache = "";
572
        }
573
        String  result = cache + (cache.contains(microRef) ? "" : microRef);
574

    
575
        String date = nomenclaturalReference.getDatePublishedString();
576
        if (isNotBlank(date) && ! result.contains(date)){
577
            result = result + beforeYear + date;
578
        }
579
        return result;
580
    }
581

    
582
    /**
583
     * Returns the nomenclatural title with micro reference represented as token
584
     * which can later be replaced by the real data.
585
     *
586
     * @see INomenclaturalReference#MICRO_REFERENCE_TOKEN
587
     */
588
    private String getTokenizedNomenclaturalTitel(Reference ref) {
589
        if (isRealInRef(ref)){
590
            return getTokenizedNomenclaturalTitelInRef(ref);
591
        }else{
592
            String result = getTitleWithoutYearAndAuthor(ref, true);
593
            result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
594
            result = addYear(result, ref, true);
595
            return result;
596
        }
597
    }
598

    
599
    private String getTokenizedNomenclaturalTitelInRef(Reference thisRef) {
600
        if (thisRef == null){
601
            return null;
602
        }
603

    
604
        Reference inRef = CdmBase.deproxy(thisRef.getInReference(), Reference.class);
605
        if (inRef != null && inRef.getInReference() != null && thisRef.getType() == ReferenceType.Section){
606
            //this is a reference of type Section which has a in-in-Ref
607
            //TODO maybe we do not need to restrict to type=Section only
608
            return this.getTokenizedNomenclaturalTitelInInRef(thisRef);
609
        }
610

    
611
        String result;
612
        //use generics's publication date if it exists
613
        if (inRef == null ||  (thisRef.hasDatePublished() ) ){
614
            result =  inRef == null ? "" : getTitleWithoutYearAndAuthorGeneric(inRef, true);
615
            //added //TODO unify with non-inRef references formatting
616

    
617
            if (isNotBlank(thisRef.getVolume())){
618
                result = result + " " + thisRef.getVolume();
619
            }
620
            //TODO series / edition
621

    
622
            //end added
623
            result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
624
            result = addYear(result, thisRef, true);
625
        }else{
626
            //else use inRefs's publication date
627
            result = inRef.getNomenclaturalCitation(INomenclaturalReference.MICRO_REFERENCE_TOKEN);
628
            if (result != null){
629
                result = result.replace(beforeMicroReference +  INomenclaturalReference.MICRO_REFERENCE_TOKEN, INomenclaturalReference.MICRO_REFERENCE_TOKEN);
630
            }
631
        }
632
        //FIXME: vol. etc., http://dev.e-taxonomy.eu/trac/ticket/2862
633

    
634
        result = getInRefAuthorPart(thisRef.getInReference(), afterInRefAuthor) + result;
635
        result = "in " +  result;
636
        return result;
637
    }
638

    
639
    /**
640
     * For handling in-in-Ref case.
641
     * Must only be called if a reference has inRef and inInRef
642
     * @param section
643
     * @return
644
     */
645
    private String getTokenizedNomenclaturalTitelInInRef(Reference ref) {
646
        String result;
647

    
648
        Reference inRef = CdmBase.deproxy(ref.getInReference(), Reference.class);
649
        Reference inInRef = CdmBase.deproxy(inRef.getInReference(), Reference.class);
650

    
651
        if (! isNomRef(inInRef.getType())){
652
            if (! isNomRef(inRef.getType())){
653
                logger.warn("Neither inReference nor inInReference is a "
654
                        + " nomenclatural reference. This is not correct or not handled yet."
655
                        + " Generic titleWithoutYearAndAuthor used instead");
656
                result = getTitleWithoutYearAndAuthorGeneric(inInRef, true);
657
                //FIXME: vol. etc., http://dev.e-taxonomy.eu/trac/ticket/2862  (comment taken from super.getTokenizedNomenclaturalTitel())
658
            }else{
659
                result = getTitleWithoutYearAndAuthor(inRef, true);
660
            }
661
        }else{
662
            result = getTitleWithoutYearAndAuthor(inInRef, true);
663
        }
664
        result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
665

    
666
        Reference dataReference = (ref.hasDatePublished() ? ref : inRef.hasDatePublished() ? inRef : inInRef);
667

    
668
        result = addYear(result, dataReference, true);
669

    
670
        result = getInRefAuthorPart(inInRef, afterInRefAuthor) + result;
671
        if (! result.startsWith("in ")){
672
            result = "in " +  result;
673
        }
674
        return result;
675
    }
676

    
677
    /**
678
     * See https://dev.e-taxonomy.eu/redmine/issues/8881
679
     */
680
    private String getInRefAuthorPart(Reference book, String seperator){
681
        if (book == null){
682
            return "";
683
        }
684

    
685
        TeamOrPersonBase<?> author = book.getAuthorship();
686
        String result;
687
        if (author == null){
688
            result = "";
689
        }else if(author.isInstanceOf(Person.class)){
690
            Person person = CdmBase.deproxy(author, Person.class);
691
            result = getInRefPerson(person);
692
        }else{
693
            Team team = CdmBase.deproxy(author, Team.class);
694
            if (team.isProtectedNomenclaturalTitleCache()){
695
                //not yet finally discussed may change in future
696
                result = team.getNomenclaturalTitle();
697
            }else if (team.isProtectedTitleCache()){
698
                //not yet finally discussed may change in future
699
                result = team.getTitleCache();
700
            }else if (team.getTeamMembers().isEmpty()){
701
                //not yet finally discussed may change in future
702
                result = team.getTitleCache();
703
            }else{
704
                result = "";
705
                int size = team.getTeamMembers().size();
706
                for (Person person : team.getTeamMembers()){
707
                    int index = team.getTeamMembers().lastIndexOf(person);
708
                    String sep = (team.isHasMoreMembers() || index != size - 1) ?
709
                            TeamDefaultCacheStrategy.STD_TEAM_CONCATINATION : TeamDefaultCacheStrategy.FINAL_TEAM_CONCATINATION;
710
                    result = CdmUtils.concat(sep, result, getInRefPerson(person));
711
                }
712
                if (team.isHasMoreMembers()){
713
                    result += TeamDefaultCacheStrategy.ET_AL_TEAM_CONCATINATION_FULL + "al.";
714
                }
715
            }
716
        }
717

    
718
        result = Nz(result);
719
        if (! result.trim().equals("")){
720
            result = result + seperator;
721
        }
722
        return result;
723
    }
724

    
725
    private String getInRefPerson(Person person) {
726
        String result;
727
        if (isNotBlank(person.getFamilyName())){
728
            result = person.getFamilyName();
729
        }else if (isNotBlank(person.getNomenclaturalTitle())){
730
            result = person.getNomenclaturalTitle();  //TODO discuss if nomTitle is really better here then titleCache
731
        }else{
732
            result = person.getTitleCache();  //maybe remove everything behind a ","
733
        }
734
        return result;
735
    }
736

    
737
    private String replaceMicroRefToken(String microReference, String string) {
738
        int index = string.indexOf(INomenclaturalReference.MICRO_REFERENCE_TOKEN);
739

    
740
        if (index > -1){
741
            String before = string.substring(0, index);
742
            String after = string.substring(index + INomenclaturalReference.MICRO_REFERENCE_TOKEN.length() );
743
            String localMicroReference = microReference.trim();   //needed ?
744
            if (after.length() > 0){
745
                if (  ("".equals(localMicroReference) && before.endsWith(after.substring(0,1)) || localMicroReference.endsWith(after.substring(0,1)))){
746
                    after = after.substring(1);
747
                }
748
            }
749
            String result = before + localMicroReference + after;
750
            return result;
751
        }else{
752
            return string;
753
        }
754
    }
755

    
756
// *************************** EXTERNAL USE *******************************************/
757

    
758
   public static String putAuthorToEndOfString(String referenceTitleCache, String authorTitleCache) {
759
       if(authorTitleCache != null){
760
           referenceTitleCache = referenceTitleCache.replace(authorTitleCache + ", ", "");
761
           referenceTitleCache += " - " + authorTitleCache;
762
       }
763
       return referenceTitleCache;
764
   }
765
}
(1-1/4)