Project

General

Profile

Download (26.3 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.time.ZonedDateTime;
12
import java.time.format.DateTimeFormatter;
13
import java.util.UUID;
14

    
15
import org.apache.commons.lang.StringUtils;
16
import org.apache.log4j.Logger;
17

    
18
import eu.etaxonomy.cdm.common.CdmUtils;
19
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
20
import eu.etaxonomy.cdm.model.common.CdmBase;
21
import eu.etaxonomy.cdm.model.common.TimePeriod;
22
import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
23
import eu.etaxonomy.cdm.model.reference.Reference;
24
import eu.etaxonomy.cdm.model.reference.ReferenceType;
25
import eu.etaxonomy.cdm.strategy.StrategyBase;
26

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

    
53
    private static final Logger logger = Logger.getLogger(DefaultReferenceCacheStrategy.class);
54

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

    
57
    //article
58
    public static final String UNDEFINED_JOURNAL = "- undefined journal -";
59
    private static final String afterAuthor = ", ";
60

    
61
    //book
62

    
63

    
64
    //(book?) section
65
    private String afterSectionAuthor = " - ";
66

    
67
    //in reference
68
    private String inSeparator = "in ";
69
    private static final String afterInRefAuthor = ", ";
70

    
71
    //common
72
    private static final String blank = " ";
73
    private static final String beforeYear = ". ";
74
    private static final String beforeMicroReference = ": ";
75
    private static final String afterYear = "";
76

    
77

    
78
    private static final boolean trim = true;
79

    
80
// ************************ FACTORY ****************************/
81

    
82
    /**
83
     * Factory method
84
     * @return
85
     */
86
    public static DefaultReferenceCacheStrategy NewInstance(){
87
        return new DefaultReferenceCacheStrategy();
88
    }
89

    
90

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

    
96
// ******************************* Main methods ******************************/
97

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

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

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

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

    
152

    
153
    /**
154
     * @param accessed
155
     * @return
156
     */
157
    private String getAccessedString(ZonedDateTime accessed) {
158
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
159
        String result = accessed.format(formatter);
160
        if (result.endsWith(" 00:00")){
161
            result = result.replace(" 00:00", "");
162
        }
163
        return result;
164
    }
165

    
166

    
167
    /**
168
     * @param result
169
     * @param reference
170
     * @return
171
     */
172
    private String addPages(String result, Reference reference) {
173
        //pages
174
        if (isNotBlank(reference.getPages())){
175
            //Removing trailing added just in case, maybe not necessary
176
            result = RemoveTrailingDot(Nz(result)).trim() + ": " + reference.getPages();
177
        }
178
        return result;
179
    }
180

    
181

    
182
    /**
183
     * @param nz
184
     * @return
185
     */
186
    private static String RemoveTrailingDot(String str) {
187
        if (str != null && str.endsWith(".")){
188
            str = str.substring(0, str.length()-1);
189
        }
190
        return str;
191
    }
192

    
193

    
194
    @Override
195
    public String getFullAbbrevTitleString(Reference reference) {
196
        if (reference == null){
197
            return null;
198
        }
199
        String result;
200
        ReferenceType type = reference.getType();
201
        boolean isAbbrev = true;
202

    
203
        if (reference.isProtectedAbbrevTitleCache()){
204
            return reference.getAbbrevTitleCache();
205
        }
206

    
207
        if (type == ReferenceType.Article){
208
            result =  getTitleWithoutYearAndAuthor(reference, isAbbrev);
209
            boolean useFullDatePublished = false;
210
            result = addYear(result, reference, useFullDatePublished);
211
            TeamOrPersonBase<?> team = reference.getAuthorship();
212
            String articleTitle = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
213
                    reference.getAbbrevTitle(), isAbbrev, trim);
214
            result = CdmUtils.concat(" ", articleTitle, result);  //Article should maybe left out for nomenclatural references (?)
215
            if (team != null &&  isNotBlank(team.getNomenclaturalTitle())){
216
                String authorSeparator = isNotBlank(articleTitle) ? afterAuthor : " ";
217
                result = team.getNomenclaturalTitle() + authorSeparator + result;
218
            }
219
        }else if (isRealInRef(reference)){
220
            result = titleCacheRealInRef(reference, isAbbrev);
221
        }else if (isNomRef(type)){
222
            //FIXME same as titleCache => try to merge, but note article case
223
            result =  getTitleWithoutYearAndAuthor(reference, isAbbrev);
224
            boolean useFullDatePublished = false;
225
            result = addYear(result, reference, useFullDatePublished);
226
            TeamOrPersonBase<?> team = reference.getAuthorship();
227

    
228
            if (team != null){
229
                String teamTitle = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
230
                        team.getNomenclaturalTitle(), isAbbrev, trim);
231
                if (teamTitle.length() > 0 ){
232
                    String concat = isNotBlank(result) ? afterAuthor : "";
233
                    result = teamTitle + concat + result;
234
                }
235
            }
236
        }else if(type == ReferenceType.Journal){
237
            result = titleCacheJournal(reference, isAbbrev);
238
        }else{
239
            result = titleCacheDefaultReference(reference, isAbbrev);
240
        }
241

    
242
        return result;
243
    }
244

    
245
    @Override
246
    public String getCitation(Reference reference) {
247
        // mostly copied from nomRefCacheStrat, refCache, journalCache
248

    
249
        if (reference == null){
250
            return null;
251
        }
252
        StringBuilder stringBuilder = new StringBuilder();
253
        TeamOrPersonBase<?> team = reference.getAuthorship();
254

    
255
        String nextConcat = "";
256

    
257
        if (team != null &&  isNotBlank(team.getTitleCache())){
258
            stringBuilder.append(team.getTitleCache() );
259
            //here is the difference between nomRef and others
260
            if (isNomRef(reference.getType())) {
261
                nextConcat = afterAuthor;
262
            }else{
263
                //FIXME check if this really makes sense
264
                stringBuilder.append(afterAuthor);
265
                nextConcat = beforeYear;
266
            }
267
        }
268

    
269
        String year = reference.getYear();
270
        if (StringUtils.isNotBlank(year)){
271
            stringBuilder.append(nextConcat + year);
272
        }
273

    
274
        return stringBuilder.toString();
275
    }
276

    
277
    @Override
278
    public String getNomenclaturalCache(Reference reference) {
279
        return this.getNomenclaturalCitation(reference, null);
280
    }
281

    
282
// ************************ TITLE CACHE SUBS ********************************************/
283

    
284
    /**
285
     * @param reference
286
     * @param type
287
     * @param inRef
288
     * @param hasInRef
289
     * @return
290
     */
291
    private String titleCacheRealInRef(Reference reference, boolean isAbbrev) {
292
        ReferenceType type = reference.getType();
293
        Reference inRef = reference.getInReference();
294
        boolean hasInRef = (inRef != null);
295

    
296
        String result;
297
        //copy from InRefDefaultCacheStrategyBase
298
        if (inRef != null){
299
            result = CdmUtils.getPreferredNonEmptyString(inRef.getTitleCache(),
300
                    inRef.getAbbrevTitleCache(), isAbbrev, trim)  ;
301
        }else{
302
            result = String.format("- undefined %s -", getUndefinedLabel(type));
303
        }
304

    
305
        //in
306
        result = inSeparator +  result;
307

    
308
        //section title
309
        String title = CdmUtils.getPreferredNonEmptyString(
310
                reference.getTitle(), reference.getAbbrevTitle(), isAbbrev, trim);
311
        if (title.length() > 0){
312
            result = title + blank + result;
313
        }
314

    
315
        //section author
316
        TeamOrPersonBase<?> thisRefTeam = reference.getAuthorship();
317
        String thisRefAuthor = "";
318
        if (thisRefTeam != null){
319
            thisRefAuthor = CdmUtils.getPreferredNonEmptyString(thisRefTeam.getTitleCache(),
320
                    thisRefTeam.getNomenclaturalTitle(), isAbbrev, trim);
321
        }
322
        result = CdmUtils.concat(afterSectionAuthor, thisRefAuthor, result);
323

    
324
        //date
325
        if (reference.getDatePublished() != null && ! reference.getDatePublished().isEmpty()){
326
            String thisRefDate = reference.getDatePublished().toString();
327
            if (hasInRef && reference.getInBook().getDatePublished() != null){
328
                TimePeriod inRefDate = reference.getInReference().getDatePublished();
329
                String inRefDateString = inRefDate.getYear();
330
                if (isNotBlank(inRefDateString)){
331
                    int pos = StringUtils.lastIndexOf(result, inRefDateString);
332
                    if (pos > -1 ){
333
                        result = result.substring(0, pos) + thisRefDate + result.substring(pos + inRefDateString.length());
334
                    }else{
335
                        logger.warn("InRefDateString (" + inRefDateString + ") could not be found in result (" + result +")");
336
                    }
337
                }else{
338
                    //avoid duplicate dots ('..')
339
                    String bYearSeparator = result.substring(result.length() -1).equals(beforeYear.substring(0, 1)) ? beforeYear.substring(1) : beforeYear;
340
                    result = result + bYearSeparator + thisRefDate + afterYear;
341
                }
342
            }else{
343
                result = result + beforeYear + thisRefDate + afterYear;
344
            }
345
        }
346
        return result;
347
    }
348

    
349

    
350
    /**
351
     * @param reference
352
     * @return
353
     */
354
    private String titleCacheJournal(Reference reference, boolean isAbbrev) {
355
        String result;
356
        //copied from Journal
357

    
358
        //title
359
        result = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
360
                reference.getAbbrevTitle(), isAbbrev, trim);
361

    
362
//          //delete .
363
//          while (result.endsWith(".")){
364
//              result = result.substring(0, result.length()-1);
365
//          }
366
//          result = addYear(result, journal);
367

    
368
        TeamOrPersonBase<?> team = reference.getAuthorship();
369
        if (team != null){
370
            String author = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
371
                    team.getNomenclaturalTitle(), isAbbrev, trim);
372
            if (StringUtils.isNotBlank(author)){
373
                result = author + afterAuthor + result;
374
            }
375
        }
376
        return result;
377
    }
378

    
379
    /**
380
     * @param reference
381
     * @param isNotAbbrev
382
     * @return
383
     */
384
    private String titleCacheDefaultReference(Reference reference, boolean isAbbrev) {
385
        String result;
386
        //copied from ReferenceDefaultCacheStrategy
387
        result = "";
388
        String titel = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
389
                reference.getAbbrevTitle(), isAbbrev, trim);
390
        if (isNotBlank(titel)){
391
            result = titel + blank;
392
        }
393
        //delete .
394
        while (result.endsWith(".")){
395
            result = result.substring(0, result.length()-1);
396
        }
397

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

    
410
// ******************************* HELPER *****************************************/
411
    @Override
412
    public String getBeforeMicroReference(){
413
        return beforeMicroReference;
414
    }
415

    
416
    private String addYear(String string, Reference nomRef, boolean useFullDatePublished){
417
        String result;
418
        if (string == null){
419
            return null;
420
        }
421
        String year = useFullDatePublished ? nomRef.getDatePublishedString() : nomRef.getYear();
422
        if (isBlank(year)){
423
            result = string + afterYear;
424
        }else{
425
            String concat = isBlank(string)  ? "" : string.endsWith(".")  ? " " : beforeYear;
426
            result = string + concat + year + afterYear;
427
        }
428
        return result;
429
    }
430

    
431
    private String getTitleWithoutYearAndAuthor(Reference ref, boolean isAbbrev){
432
        return TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthor(ref, isAbbrev);
433
    }
434
    private String getTitleWithoutYearAndAuthorGeneric(Reference ref, boolean isAbbrev){
435
        return TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthorGeneric(ref, isAbbrev);
436
    }
437

    
438
    /**
439
     * @param type
440
     * @return
441
     */
442
    private Object getUndefinedLabel(ReferenceType type) {
443
        if (type == ReferenceType.BookSection){
444
            return "book";
445
        }else if (type == ReferenceType.Generic){
446
            return "generic reference";
447
        }else if (type == ReferenceType.Section){
448
            return "in reference";
449
        } else {
450
            return type.getMessage();
451
        }
452
    }
453

    
454

    
455
    /**
456
     * Returns <code>true</code> if the type of the reference originally corresponded to a cache strategy
457
     * which inherited from {@link InRefDefaultCacheStrategyBase} and in case of type {@link ReferenceType#Generic}
458
     * if it really has an inreference (reference.getInreference() != null).
459
     * @param reference
460
     */
461
    private boolean isRealInRef(Reference reference) {
462
        ReferenceType type = (reference.getType());
463
        if (type == null){
464
            return false;
465
        }else if (type == ReferenceType.BookSection || type == ReferenceType.Section){
466
            return true;
467
        }else if (type == ReferenceType.Generic){
468
            return reference.getInReference() != null;
469
        }else{
470
            return false;
471
        }
472
    }
473

    
474
    /**
475
     * Returns <code>true</code> if the type of the reference originally corresponded to a cache strategy
476
     * which inherited from {@link NomRefDefaultCacheStrategyBase}.
477
     * @param type
478
     */
479
    protected static boolean isNomRef(ReferenceType type){
480
        switch (type){
481
            case Article:
482
            case Book:
483
            case BookSection:
484
            case CdDvd:
485
            case Generic:
486
            case Section:
487
            case Thesis:
488
            case WebPage:
489
                return true;
490

    
491
            case Journal:
492
            default:
493
                return false;
494
        }
495
    }
496

    
497
    /**
498
     * Returns year information as originally computed by {@link ReferenceDefaultCacheStrategy}
499
     * @param string
500
     * @param ref
501
     * @return
502
     */
503
    private String addYearReferenceDefault(String string, Reference ref){
504
        String result;
505
        if (string == null){
506
            return null;
507
        }
508
        String year = CdmUtils.Nz(ref.getYear());
509
        if ("".equals(year)){
510
            result = string + afterYear;
511
        }else{
512
            result = string + beforeYear + year + afterYear;
513
        }
514
        return result;
515
    }
516

    
517

    
518
// ********************* Nomenclatural title ***************************************/
519

    
520
    @Override
521
    public String getNomenclaturalCitation(Reference reference, String microReference) {
522
        if (reference.isProtectedAbbrevTitleCache()){
523
            String cache = reference.getAbbrevTitleCache();
524
            return handleDetailAndYearForPreliminary(reference, cache, microReference);
525

    
526
        }
527
        String result = getTokenizedNomenclaturalTitel(reference);
528
        //if no data is available and only titleCache is protected take the protected title
529
        //this is to avoid empty cache if someone forgets to set also the abbrevTitleCache
530
        //we need to think about handling protected not separate for abbrevTitleCache  and titleCache
531
        if (result.equals(INomenclaturalReference.MICRO_REFERENCE_TOKEN) && reference.isProtectedTitleCache() ){
532
            String cache = reference.getTitleCache();
533
            return handleDetailAndYearForPreliminary(reference, cache, microReference);
534
        }
535

    
536
        microReference = Nz(microReference);
537
        if (StringUtils.isNotBlank(microReference)){
538
            microReference = getBeforeMicroReference() + microReference;
539
            if (microReference.endsWith(".")  && result.contains(INomenclaturalReference.MICRO_REFERENCE_TOKEN + ".") ){
540
                microReference = microReference.substring(0, microReference.length() - 1);
541
            }
542
        }
543
        result = replaceMicroRefToken(microReference, result);
544
        if (result.startsWith(". ")){  //only year available, remove '. '
545
            result = result.substring(2);
546
        }
547
        return result;
548
    }
549

    
550
    /**
551
     * @param nomenclaturalReference
552
     * @param microRef
553
     * @return
554
     */
555
    private String handleDetailAndYearForPreliminary(Reference nomenclaturalReference, String cache, String microReference) {
556
        String microRef = isNotBlank(microReference) ? getBeforeMicroReference() + microReference : "";
557
        if (cache == null){
558
            logger.warn("Cache is null. This should never be the case.");
559
            cache = "";
560
        }
561
        String  result = cache + (cache.contains(microRef) ? "" : microRef);
562

    
563
        String date = nomenclaturalReference.getDatePublishedString();
564
        if (isNotBlank(date) && ! result.contains(date)){
565
            result = result + beforeYear + date;
566
        }
567
        return result;
568
    }
569

    
570
    /**
571
     * Returns the nomenclatural title with micro reference represented as token
572
     * which can later be replaced by the real data.
573
     *
574
     * @see INomenclaturalReference#MICRO_REFERENCE_TOKEN
575
     *
576
     * @param ref The reference
577
     * @return
578
     */
579
    private String getTokenizedNomenclaturalTitel(Reference ref) {
580
        if (isRealInRef(ref)){
581
            return getTokenizedNomenclaturalTitelInRef(ref);
582
        }else{
583
            String result = getTitleWithoutYearAndAuthor(ref, true);
584
            result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
585
            result = addYear(result, ref, true);
586
            return result;
587
        }
588
    }
589

    
590
    private String getTokenizedNomenclaturalTitelInRef(Reference thisRef) {
591
        if (thisRef == null){
592
            return null;
593
        }
594

    
595
        Reference inRef = CdmBase.deproxy(thisRef.getInReference(), Reference.class);
596
        if (inRef != null && inRef.getInReference() != null && thisRef.getType() == ReferenceType.Section){
597
            //this is a reference of type Section which has a in-in-Ref
598
            //TODO maybe we do not need to restrict to type=Section only
599
            return this.getTokenizedNomenclaturalTitelInInRef(thisRef);
600
        }
601

    
602
        String result;
603
        //use generics's publication date if it exists
604
        if (inRef == null ||  (thisRef.hasDatePublished() ) ){
605
            getTitleWithoutYearAndAuthorGeneric(inRef, true);
606
            result =  inRef == null ? "" : getTitleWithoutYearAndAuthorGeneric(inRef, true);
607
            //added //TODO unify with non-inRef references formatting
608

    
609
            if (isNotBlank(thisRef.getVolume())){
610
                result = result + " " + thisRef.getVolume();
611
            }
612
            //TODO series / edition
613

    
614
            //end added
615
            result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
616
            result = addYear(result, thisRef, true);
617
        }else{
618
            //else use inRefs's publication date
619
            result = inRef.getNomenclaturalCitation(INomenclaturalReference.MICRO_REFERENCE_TOKEN);
620
            if (result != null){
621
                result = result.replace(beforeMicroReference +  INomenclaturalReference.MICRO_REFERENCE_TOKEN, INomenclaturalReference.MICRO_REFERENCE_TOKEN);
622
            }
623
        }
624
        //FIXME: vol. etc., http://dev.e-taxonomy.eu/trac/ticket/2862
625

    
626
        result = getInRefAuthorPart(thisRef.getInReference(), afterInRefAuthor) + result;
627
        result = "in " +  result;
628
        return result;
629
    }
630

    
631
    /**
632
     * For handling in-in-Ref case.
633
     * Must only be called if a reference has inRef and inInRef
634
     * @param section
635
     * @return
636
     */
637
    private String getTokenizedNomenclaturalTitelInInRef(Reference ref) {
638
        String result;
639

    
640
        Reference inRef = CdmBase.deproxy(ref.getInReference(), Reference.class);
641
        Reference inInRef = CdmBase.deproxy(inRef.getInReference(), Reference.class);
642

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

    
658
        Reference dataReference = (ref.hasDatePublished() ? ref : inRef.hasDatePublished() ? inRef : inInRef);
659

    
660
        result = addYear(result, dataReference, true);
661

    
662
        result = getInRefAuthorPart(inInRef, afterInRefAuthor) + result;
663
        if (! result.startsWith("in ")){
664
            result = "in " +  result;
665
        }
666
        return result;
667
    }
668

    
669
    private String getInRefAuthorPart(Reference book, String seperator){
670
        if (book == null){
671
            return "";
672
        }
673
        TeamOrPersonBase<?> team = book.getAuthorship();
674
        String result = Nz( team == null ? "" : team.getNomenclaturalTitle());
675
        if (! result.trim().equals("")){
676
            result = result + seperator;
677
        }
678
        return result;
679
    }
680

    
681

    
682
    /**
683
     * @param microReference
684
     * @param result
685
     * @return
686
     */
687
    private String replaceMicroRefToken(String microReference, String string) {
688
        int index = string.indexOf(INomenclaturalReference.MICRO_REFERENCE_TOKEN);
689

    
690
        if (index > -1){
691
            String before = string.substring(0, index);
692
            String after = string.substring(index + INomenclaturalReference.MICRO_REFERENCE_TOKEN.length() );
693
            String localMicroReference = microReference.trim();   //needed ?
694
            if (after.length() > 0){
695
                if (  ("".equals(localMicroReference) && before.endsWith(after.substring(0,1)) || localMicroReference.endsWith(after.substring(0,1)))){
696
                    after = after.substring(1);
697
                }
698
            }
699
            String result = before + localMicroReference + after;
700
            return result;
701
        }else{
702
            return string;
703
        }
704
    }
705

    
706
// *************************** EXTERNAL USE *******************************************/
707
   /**
708
    *
709
    * @param referenceTitleCache
710
    * @param authorTitleCache
711
    * @return
712
    */
713
   public static String putAuthorToEndOfString(String referenceTitleCache, String authorTitleCache) {
714
       if(authorTitleCache != null){
715
           referenceTitleCache = referenceTitleCache.replace(authorTitleCache + ", ", "");
716
           referenceTitleCache += " - " + authorTitleCache;
717
       }
718
       return referenceTitleCache;
719
   }
720
}
(1-1/4)