Project

General

Profile

Download (24.7 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2016 EDIT
4
* European Distributed Institute of Taxonomy
5
* http://www.e-taxonomy.eu
6
*
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10
package eu.etaxonomy.cdm.strategy.cache.reference;
11

    
12
import java.util.UUID;
13

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

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

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

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

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

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

    
60
    //book
61

    
62

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

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

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

    
76

    
77
    private static final boolean trim = true;
78

    
79
// ************************ FACTORY ****************************/
80

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

    
89

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

    
95
// ******************************* Main methods ******************************/
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 = addYear(result, reference, false);
116
            TeamOrPersonBase<?> team = reference.getAuthorship();
117

    
118
            if (type == ReferenceType.Article){
119
                result = CdmUtils.concat(" ", reference.getTitle(), result);
120
                if (team != null &&  isNotBlank(team.getTitleCache())){
121
                    String authorSeparator = isNotBlank(reference.getTitle())? afterAuthor : " ";
122
                    result = team.getTitleCache() + authorSeparator + result;
123
                }
124
            }else{  //if Book, CdDvd, flat Generic, Thesis, WebPage
125
                if (team != null){
126
                    String teamTitle = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
127
                            team.getNomenclaturalTitle(), isNotAbbrev, trim);
128
                    if (teamTitle.length() > 0 ){
129
                        String concat = isNotBlank(result) ? afterAuthor : "";
130
                        result = teamTitle + concat + result;
131
                    }
132
                }
133
            }
134
        }else if (type == ReferenceType.Journal){
135
            result = titleCacheJournal(reference, isNotAbbrev);
136
        }else{
137
            result = titleCacheDefaultReference(reference, isNotAbbrev);
138
        }
139
        return result;
140
    }
141

    
142

    
143
    @Override
144
    public String getFullAbbrevTitleString(Reference reference) {
145
        if (reference == null){
146
            return null;
147
        }
148
        String result;
149
        ReferenceType type = reference.getType();
150
        boolean isAbbrev = true;
151

    
152
        if (reference.isProtectedAbbrevTitleCache()){
153
            return reference.getAbbrevTitleCache();
154
        }
155

    
156
        if (type == ReferenceType.Article){
157
            result =  getTitleWithoutYearAndAuthor(reference, isAbbrev);
158
            boolean useFullDatePublished = false;
159
            result = addYear(result, reference, useFullDatePublished);
160
            TeamOrPersonBase<?> team = reference.getAuthorship();
161
            String articleTitle = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
162
                    reference.getAbbrevTitle(), isAbbrev, trim);
163
            result = CdmUtils.concat(" ", articleTitle, result);  //Article should maybe left out for nomenclatural references (?)
164
            if (team != null &&  isNotBlank(team.getNomenclaturalTitle())){
165
                String authorSeparator = isNotBlank(articleTitle) ? afterAuthor : " ";
166
                result = team.getNomenclaturalTitle() + authorSeparator + result;
167
            }
168
        }else if (isRealInRef(reference)){
169
            result = titleCacheRealInRef(reference, isAbbrev);
170
        }else if (isNomRef(type)){
171
            //FIXME same as titleCache => try to merge, but note article case
172
            result =  getTitleWithoutYearAndAuthor(reference, isAbbrev);
173
            boolean useFullDatePublished = false;
174
            result = addYear(result, reference, useFullDatePublished);
175
            TeamOrPersonBase<?> team = reference.getAuthorship();
176

    
177
            if (team != null){
178
                String teamTitle = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
179
                        team.getNomenclaturalTitle(), isAbbrev, trim);
180
                if (teamTitle.length() > 0 ){
181
                    String concat = isNotBlank(result) ? afterAuthor : "";
182
                    result = teamTitle + concat + result;
183
                }
184
            }
185
        }else if(type == ReferenceType.Journal){
186
            result = titleCacheJournal(reference, isAbbrev);
187
        }else{
188
            result = titleCacheDefaultReference(reference, isAbbrev);
189
        }
190

    
191
        return result;
192
    }
193

    
194
    @Override
195
    public String getCitation(Reference reference) {
196
        // mostly copied from nomRefCacheStrat, refCache, journalCache
197

    
198
        if (reference == null){
199
            return null;
200
        }
201
        StringBuilder stringBuilder = new StringBuilder();
202
        TeamOrPersonBase<?> team = reference.getAuthorship();
203

    
204
        String nextConcat = "";
205

    
206
        if (team != null &&  isNotBlank(team.getTitleCache())){
207
            stringBuilder.append(team.getTitleCache() );
208
            //here is the difference between nomRef and others
209
            if (isNomRef(reference.getType())) {
210
                nextConcat = afterAuthor;
211
            }else{
212
                //FIXME check if this really makes sense
213
                stringBuilder.append(afterAuthor);
214
                nextConcat = beforeYear;
215
            }
216
        }
217

    
218
        String year = reference.getYear();
219
        if (StringUtils.isNotBlank(year)){
220
            stringBuilder.append(nextConcat + year);
221
        }
222

    
223
        return stringBuilder.toString();
224
    }
225

    
226
    @Override
227
    public String getNomenclaturalCache(Reference reference) {
228
        return this.getNomenclaturalCitation(reference, null);
229
    }
230

    
231
// ************************ TITLE CACHE SUBS ********************************************/
232

    
233
    /**
234
     * @param reference
235
     * @param type
236
     * @param inRef
237
     * @param hasInRef
238
     * @return
239
     */
240
    private String titleCacheRealInRef(Reference reference, boolean isAbbrev) {
241
        ReferenceType type = reference.getType();
242
        Reference inRef = reference.getInReference();
243
        boolean hasInRef = (inRef != null);
244

    
245
        String result;
246
        //copy from InRefDefaultCacheStrategyBase
247
        if (inRef != null){
248
            result = CdmUtils.getPreferredNonEmptyString(inRef.getTitleCache(),
249
                    inRef.getAbbrevTitleCache(), isAbbrev, trim)  ;
250
        }else{
251
            result = String.format("- undefined %s -", getUndefinedLabel(type));
252
        }
253

    
254
        //in
255
        result = inSeparator +  result;
256

    
257
        //section title
258
        String title = CdmUtils.getPreferredNonEmptyString(
259
                reference.getTitle(), reference.getAbbrevTitle(), isAbbrev, trim);
260
        if (title.length() > 0){
261
            result = title + blank + result;
262
        }
263

    
264
        //section author
265
        TeamOrPersonBase<?> thisRefTeam = reference.getAuthorship();
266
        String thisRefAuthor = "";
267
        if (thisRefTeam != null){
268
            thisRefAuthor = CdmUtils.getPreferredNonEmptyString(thisRefTeam.getTitleCache(),
269
                    thisRefTeam.getNomenclaturalTitle(), isAbbrev, trim);
270
        }
271
        result = CdmUtils.concat(afterSectionAuthor, thisRefAuthor, result);
272

    
273
        //date
274
        if (reference.getDatePublished() != null && ! reference.getDatePublished().isEmpty()){
275
            String thisRefDate = reference.getDatePublished().toString();
276
            if (hasInRef && reference.getInBook().getDatePublished() != null){
277
                TimePeriod inRefDate = reference.getInReference().getDatePublished();
278
                String inRefDateString = inRefDate.getYear();
279
                if (isNotBlank(inRefDateString)){
280
                    int pos = StringUtils.lastIndexOf(result, inRefDateString);
281
                    if (pos > -1 ){
282
                        result = result.substring(0, pos) + thisRefDate + result.substring(pos + inRefDateString.length());
283
                    }else{
284
                        logger.warn("InRefDateString (" + inRefDateString + ") could not be found in result (" + result +")");
285
                    }
286
                }else{
287
                    //avoid duplicate dots ('..')
288
                    String bYearSeparator = result.substring(result.length() -1).equals(beforeYear.substring(0, 1)) ? beforeYear.substring(1) : beforeYear;
289
                    result = result + bYearSeparator + thisRefDate + afterYear;
290
                }
291
            }else{
292
                result = result + beforeYear + thisRefDate + afterYear;
293
            }
294
        }
295
        return result;
296
    }
297

    
298

    
299
    /**
300
     * @param reference
301
     * @return
302
     */
303
    private String titleCacheJournal(Reference reference, boolean isAbbrev) {
304
        String result;
305
        //copied from Journal
306

    
307
        //title
308
        result = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
309
                reference.getAbbrevTitle(), isAbbrev, trim);
310

    
311
//          //delete .
312
//          while (result.endsWith(".")){
313
//              result = result.substring(0, result.length()-1);
314
//          }
315
//          result = addYear(result, journal);
316

    
317
        TeamOrPersonBase<?> team = reference.getAuthorship();
318
        if (team != null){
319
            String author = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
320
                    team.getNomenclaturalTitle(), isAbbrev, trim);
321
            if (StringUtils.isNotBlank(author)){
322
                result = author + afterAuthor + result;
323
            }
324
        }
325
        return result;
326
    }
327

    
328
    /**
329
     * @param reference
330
     * @param isNotAbbrev
331
     * @return
332
     */
333
    private String titleCacheDefaultReference(Reference reference, boolean isAbbrev) {
334
        String result;
335
        //copied from ReferenceDefaultCacheStrategy
336
        result = "";
337
        String titel = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
338
                reference.getAbbrevTitle(), isAbbrev, trim);
339
        if (isNotBlank(titel)){
340
            result = titel + blank;
341
        }
342
        //delete .
343
        while (result.endsWith(".")){
344
            result = result.substring(0, result.length()-1);
345
        }
346

    
347
        result = addYearReferenceDefault(result, reference);
348
        TeamOrPersonBase<?> team = reference.getAuthorship();
349
        if (team != null){
350
            String author = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
351
                    team.getNomenclaturalTitle(), isAbbrev, trim);
352
            if (isNotBlank(author)){
353
                result = author + afterAuthor + result;
354
            }
355
        }
356
        return result;
357
    }
358

    
359
// ******************************* HELPER *****************************************/
360
    @Override
361
    public String getBeforeMicroReference(){
362
        return beforeMicroReference;
363
    }
364

    
365
    private String addYear(String string, Reference nomRef, boolean useFullDatePublished){
366
        String result;
367
        if (string == null){
368
            return null;
369
        }
370
        String year = useFullDatePublished ? nomRef.getDatePublishedString() : nomRef.getYear();
371
        if (isBlank(year)){
372
            result = string + afterYear;
373
        }else{
374
            String concat = isBlank(string)  ? "" : string.endsWith(".")  ? " " : beforeYear;
375
            result = string + concat + year + afterYear;
376
        }
377
        return result;
378
    }
379

    
380
    private String getTitleWithoutYearAndAuthor(Reference ref, boolean isAbbrev){
381
        return TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthor(ref, isAbbrev);
382
    }
383
    private String getTitleWithoutYearAndAuthorGeneric(Reference ref, boolean isAbbrev){
384
        return TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthorGeneric(ref, isAbbrev);
385
    }
386

    
387
    /**
388
     * @param type
389
     * @return
390
     */
391
    private Object getUndefinedLabel(ReferenceType type) {
392
        if (type == ReferenceType.BookSection){
393
            return "book";
394
        }else if (type == ReferenceType.Generic){
395
            return "generic reference";
396
        }else if (type == ReferenceType.Section){
397
            return "in reference";
398
        } else {
399
            return type.getMessage();
400
        }
401
    }
402

    
403

    
404
    /**
405
     * Returns <code>true</code> if the type of the reference originally corresponded to a cache strategy
406
     * which inherited from {@link InRefDefaultCacheStrategyBase} and in case of type {@link ReferenceType#Generic}
407
     * if it really has an inreference (reference.getInreference() != null).
408
     * @param reference
409
     */
410
    private boolean isRealInRef(Reference reference) {
411
        ReferenceType type = (reference.getType());
412
        if (type == null){
413
            return false;
414
        }else if (type == ReferenceType.BookSection || type == ReferenceType.Section){
415
            return true;
416
        }else if (type == ReferenceType.Generic){
417
            return reference.getInReference() != null;
418
        }else{
419
            return false;
420
        }
421
    }
422

    
423
    /**
424
     * Returns <code>true</code> if the type of the reference originally corresponded to a cache strategy
425
     * which inherited from {@link NomRefDefaultCacheStrategyBase}.
426
     * @param type
427
     */
428
    protected static boolean isNomRef(ReferenceType type){
429
        switch (type){
430
            case Article:
431
            case Book:
432
            case BookSection:
433
            case CdDvd:
434
            case Generic:
435
            case Section:
436
            case Thesis:
437
            case WebPage:
438
                return true;
439

    
440
            case Journal:
441
            default:
442
                return false;
443
        }
444
    }
445

    
446
    /**
447
     * Returns year information as originally computed by {@link ReferenceDefaultCacheStrategy}
448
     * @param string
449
     * @param ref
450
     * @return
451
     */
452
    private String addYearReferenceDefault(String string, Reference ref){
453
        String result;
454
        if (string == null){
455
            return null;
456
        }
457
        String year = CdmUtils.Nz(ref.getYear());
458
        if ("".equals(year)){
459
            result = string + afterYear;
460
        }else{
461
            result = string + beforeYear + year + afterYear;
462
        }
463
        return result;
464
    }
465

    
466

    
467
// ********************* Nomenclatural title ***************************************/
468

    
469
    @Override
470
    public String getNomenclaturalCitation(Reference reference, String microReference) {
471
        if (reference.isProtectedAbbrevTitleCache()){
472
            String cache = reference.getAbbrevTitleCache();
473
            return handleDetailAndYearForPreliminary(reference, cache, microReference);
474

    
475
        }
476
        String result = getTokenizedNomenclaturalTitel(reference);
477
        //if no data is available and only titleCache is protected take the protected title
478
        //this is to avoid empty cache if someone forgets to set also the abbrevTitleCache
479
        //we need to think about handling protected not separate for abbrevTitleCache  and titleCache
480
        if (result.equals(INomenclaturalReference.MICRO_REFERENCE_TOKEN) && reference.isProtectedTitleCache() ){
481
            String cache = reference.getTitleCache();
482
            return handleDetailAndYearForPreliminary(reference, cache, microReference);
483
        }
484

    
485
        microReference = Nz(microReference);
486
        if (StringUtils.isNotBlank(microReference)){
487
            microReference = getBeforeMicroReference() + microReference;
488
            if (microReference.endsWith(".")  && result.contains(INomenclaturalReference.MICRO_REFERENCE_TOKEN + ".") ){
489
                microReference = microReference.substring(0, microReference.length() - 1);
490
            }
491
        }
492
        result = replaceMicroRefToken(microReference, result);
493
        if (result.startsWith(". ")){  //only year available, remove '. '
494
            result = result.substring(2);
495
        }
496
        return result;
497
    }
498

    
499
    /**
500
     * @param nomenclaturalReference
501
     * @param microRef
502
     * @return
503
     */
504
    private String handleDetailAndYearForPreliminary(Reference nomenclaturalReference, String cache, String microReference) {
505
        String microRef = isNotBlank(microReference) ? getBeforeMicroReference() + microReference : "";
506
        if (cache == null){
507
            logger.warn("Cache is null. This should never be the case.");
508
            cache = "";
509
        }
510
        String  result = cache + (cache.contains(microRef) ? "" : microRef);
511

    
512
        String date = nomenclaturalReference.getDatePublishedString();
513
        if (isNotBlank(date) && ! result.contains(date)){
514
            result = result + beforeYear + date;
515
        }
516
        return result;
517
    }
518

    
519
    /**
520
     * Returns the nomenclatural title with micro reference represented as token
521
     * which can later be replaced by the real data.
522
     *
523
     * @see INomenclaturalReference#MICRO_REFERENCE_TOKEN
524
     *
525
     * @param ref The reference
526
     * @return
527
     */
528
    private String getTokenizedNomenclaturalTitel(Reference ref) {
529
        if (isRealInRef(ref)){
530
            return getTokenizedNomenclaturalTitelInRef(ref);
531
        }else{
532
            String result = getTitleWithoutYearAndAuthor(ref, true);
533
            result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
534
            result = addYear(result, ref, true);
535
            return result;
536
        }
537
    }
538

    
539
    private String getTokenizedNomenclaturalTitelInRef(Reference thisRef) {
540
        if (thisRef == null){
541
            return null;
542
        }
543

    
544
        Reference inRef = CdmBase.deproxy(thisRef.getInReference(), Reference.class);
545
        if (inRef != null && inRef.getInReference() != null && thisRef.getType() == ReferenceType.Section){
546
            //this is a reference of type Section which has a in-in-Ref
547
            //TODO maybe we do not need to restrict to type=Section only
548
            return this.getTokenizedNomenclaturalTitelInInRef(thisRef);
549
        }
550

    
551
        String result;
552
        //use generics's publication date if it exists
553
        if (inRef == null ||  (thisRef.hasDatePublished() ) ){
554
            getTitleWithoutYearAndAuthorGeneric(inRef, true);
555
            result =  inRef == null ? "" : getTitleWithoutYearAndAuthorGeneric(inRef, true);
556
            //added //TODO unify with non-inRef references formatting
557

    
558
            if (isNotBlank(thisRef.getVolume())){
559
                result = result + " " + thisRef.getVolume();
560
            }
561
            //TODO series / edition
562

    
563
            //end added
564
            result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
565
            result = addYear(result, thisRef, true);
566
        }else{
567
            //else use inRefs's publication date
568
            result = inRef.getNomenclaturalCitation(INomenclaturalReference.MICRO_REFERENCE_TOKEN);
569
            if (result != null){
570
                result = result.replace(beforeMicroReference +  INomenclaturalReference.MICRO_REFERENCE_TOKEN, INomenclaturalReference.MICRO_REFERENCE_TOKEN);
571
            }
572
        }
573
        //FIXME: vol. etc., http://dev.e-taxonomy.eu/trac/ticket/2862
574

    
575
        result = getInRefAuthorPart(thisRef.getInReference(), afterInRefAuthor) + result;
576
        result = "in " +  result;
577
        return result;
578
    }
579

    
580
    /**
581
     * For handling in-in-Ref case.
582
     * Must only be called if a reference has inRef and inInRef
583
     * @param section
584
     * @return
585
     */
586
    private String getTokenizedNomenclaturalTitelInInRef(Reference ref) {
587
        String result;
588

    
589
        Reference inRef = CdmBase.deproxy(ref.getInReference(), Reference.class);
590
        Reference inInRef = CdmBase.deproxy(inRef.getInReference(), Reference.class);
591

    
592
        if (! isNomRef(inInRef.getType())){
593
            if (! isNomRef(inRef.getType())){
594
                logger.warn("Neither inReference nor inInReference is a "
595
                        + " nomenclatural reference. This is not correct or not handled yet."
596
                        + " Generic titleWithoutYearAndAuthor used instead");
597
                result = getTitleWithoutYearAndAuthorGeneric(inInRef, true);
598
                //FIXME: vol. etc., http://dev.e-taxonomy.eu/trac/ticket/2862  (comment taken from super.getTokenizedNomenclaturalTitel())
599
            }else{
600
                result = getTitleWithoutYearAndAuthor(inRef, true);
601
            }
602
        }else{
603
            result = getTitleWithoutYearAndAuthor(inInRef, true);
604
        }
605
        result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
606

    
607
        Reference dataReference = (ref.hasDatePublished() ? ref : inRef.hasDatePublished() ? inRef : inInRef);
608

    
609
        result = addYear(result, dataReference, true);
610

    
611
        result = getInRefAuthorPart(inInRef, afterInRefAuthor) + result;
612
        if (! result.startsWith("in ")){
613
            result = "in " +  result;
614
        }
615
        return result;
616
    }
617

    
618
    private String getInRefAuthorPart(Reference book, String seperator){
619
        if (book == null){
620
            return "";
621
        }
622
        TeamOrPersonBase<?> team = book.getAuthorship();
623
        String result = Nz( team == null ? "" : team.getNomenclaturalTitle());
624
        if (! result.trim().equals("")){
625
            result = result + seperator;
626
        }
627
        return result;
628
    }
629

    
630

    
631
    /**
632
     * @param microReference
633
     * @param result
634
     * @return
635
     */
636
    private String replaceMicroRefToken(String microReference, String string) {
637
        int index = string.indexOf(INomenclaturalReference.MICRO_REFERENCE_TOKEN);
638

    
639
        if (index > -1){
640
            String before = string.substring(0, index);
641
            String after = string.substring(index + INomenclaturalReference.MICRO_REFERENCE_TOKEN.length() );
642
            String localMicroReference = microReference.trim();   //needed ?
643
            if (after.length() > 0){
644
                if (  ("".equals(localMicroReference) && before.endsWith(after.substring(0,1)) || localMicroReference.endsWith(after.substring(0,1)))){
645
                    after = after.substring(1);
646
                }
647
            }
648
            String result = before + localMicroReference + after;
649
            return result;
650
        }else{
651
            return string;
652
        }
653
    }
654

    
655
// *************************** EXTERNAL USE *******************************************/
656
   /**
657
    *
658
    * @param referenceTitleCache
659
    * @param authorTitleCache
660
    * @return
661
    */
662
   public static String putAuthorToEndOfString(String referenceTitleCache, String authorTitleCache) {
663
       if(authorTitleCache != null){
664
           referenceTitleCache = referenceTitleCache.replace(authorTitleCache + ", ", "");
665
           referenceTitleCache += " - " + authorTitleCache;
666
       }
667
       return referenceTitleCache;
668
   }
669
}
(1-1/4)