Project

General

Profile

Download (20.1 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.UUID;
12

    
13
import org.apache.log4j.Logger;
14
import org.joda.time.DateTime;
15
import org.joda.time.format.DateTimeFormat;
16
import org.joda.time.format.DateTimeFormatter;
17

    
18
import eu.etaxonomy.cdm.common.CdmUtils;
19
import eu.etaxonomy.cdm.common.UTF8;
20
import eu.etaxonomy.cdm.format.reference.NomenclaturalSourceFormatter;
21
import eu.etaxonomy.cdm.format.reference.OriginalSourceFormatter;
22
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
23
import eu.etaxonomy.cdm.model.common.VerbatimTimePeriod;
24
import eu.etaxonomy.cdm.model.reference.Reference;
25
import eu.etaxonomy.cdm.model.reference.ReferenceType;
26
import eu.etaxonomy.cdm.strategy.StrategyBase;
27

    
28
/**
29
 * #5833
30
 * The new single default cache strategy for {@link Reference references}.
31
 * As we do have only one {@link Reference} class left which implements multiple interfaces,
32
 * we may also only need 1 single cache strategy. However, care must be taken as the formatting
33
 * differs dependent on the type an the in-reference structure.
34
 *
35
 * Generally the cache strategy allows to compute 2 formats:<BR><BR>
36
 *
37
 *  1.) for bibliographic references (stored in {@link Reference#getTitleCache() titleCache}).<BR>
38
 *
39
 *  2.) for nomenclatural references (stored in {@link Reference#getAbbrevTitleCache() abbrevTitleCache}),
40
 *      but without micro reference (detail).<BR>
41
 * <BR>
42
 * The formatting of nomenclatural references with micro references has been moved to {@link NomenclaturalSourceFormatter}
43
 * and the formatting of short citations has been moved to {@link OriginalSourceFormatter}.
44
 *
45
 * @author a.mueller
46
 * @since 25.05.2016
47
 */
48
public class ReferenceDefaultCacheStrategy
49
        extends StrategyBase
50
        implements IReferenceCacheStrategy {
51

    
52
    private static final long serialVersionUID = 6773742298840407263L;
53
    @SuppressWarnings("unused")
54
    private static final Logger logger = Logger.getLogger(ReferenceDefaultCacheStrategy.class);
55

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

    
58
    private static final String afterAuthor = ": ";
59
    private static final String afterInRefAuthor = ", ";  //TODO needs discussion
60

    
61
    //article
62
    public static final String UNDEFINED_JOURNAL = "undefined journal " + UTF8.EN_DASH;
63

    
64
    //in reference
65
    private static String biblioInSeparator = " " + UTF8.EN_DASH + " In: "; //#9529
66
    private String biblioArticleInSeparator = UTF8.EN_DASH + " "; //#9529
67
    private String webpageUriSeparator = " "+UTF8.EN_DASH+" ";
68

    
69
    //common
70
    private static final String blank = " ";
71
    public static final String beforeYear = ". ";
72
    private static final String afterYear = "";
73

    
74
    private static final boolean trim = true;
75

    
76
    private final NomenclaturalSourceFormatter nomSourceFormatter = NomenclaturalSourceFormatter.INSTANCE();
77

    
78
// ************************ FACTORY ****************************/
79

    
80
    public static ReferenceDefaultCacheStrategy NewInstance(){
81
        return new ReferenceDefaultCacheStrategy();
82
    }
83

    
84
// ******************************* Main methods ******************************/
85

    
86
    @Override
87
    protected UUID getUuid() {
88
        return uuid;
89
    }
90

    
91
    @Override
92
    public String getTitleCache(Reference reference) {
93
        if (reference == null){
94
            return null;
95
        }
96
        if (reference.isProtectedTitleCache()){
97
            return reference.getTitleCache();
98
        }
99
        boolean isNotAbbrev = false;
100

    
101
        String result;
102
        ReferenceType type = reference.getType();
103
        String authorAndYear = getAuthorAndYear(reference, isNotAbbrev, false);
104

    
105
        if (isRealInRef(reference)){
106
            //Section, Book-Section or Generic with inRef
107
            result = titleCacheRealInRef(reference, isNotAbbrev);
108
        }else if(isNomRef(type)){
109
            //all Non-InRef NomRefs
110
            //Article, CdDvd, Generic, Section, Thesis, WebPage (+Book, BookSection but not here)
111
            String title = getTitleWithoutYearAndAuthor(reference, isNotAbbrev, false);
112
            result = addPages(title, reference);
113
            if (isNotBlank(authorAndYear)){
114
                String authorSeparator = isNotBlank(title)? afterAuthor : "";
115
                authorAndYear += authorSeparator;
116
            }
117
            result = authorAndYear + result;
118
        }else if (type == ReferenceType.Journal){
119
            result = titleCacheJournal(reference, isNotAbbrev);
120
        }else{
121
            result = titleCacheDefaultReference(reference, isNotAbbrev);
122
        }
123
        if (reference.getType() == ReferenceType.WebPage && reference.getUri() != null && !result.contains(reference.getUri().toString())){
124
            result = CdmUtils.concat(webpageUriSeparator, result, reference.getUri().toString());
125
        }
126
        if(reference.getAccessed() != null){
127
            //TODO still a bit preliminary, also brackets may change in future
128
            result = result + " [accessed " + getAccessedString(reference.getAccessed()) +"]";
129
        }
130
        return result == null ? null : result.trim();
131
    }
132

    
133
    private String getAuthorAndYear(Reference reference, boolean isAbbrev, boolean useFullDatePublished) {
134
        TeamOrPersonBase<?> author = reference.getAuthorship();
135
        String authorStr = (author == null)? "" : CdmUtils.getPreferredNonEmptyString(author.getTitleCache(),
136
                author.getNomenclaturalTitle(), isAbbrev, trim);
137
        String result = addAuthorYear(authorStr, reference, useFullDatePublished);
138
        return result;
139
    }
140

    
141
    private String getAccessedString(DateTime accessed) {
142
        DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm");
143
        String result = formatter.print(accessed);
144
        if (result.endsWith(" 00:00")){
145
            result = result.replace(" 00:00", "");
146
        }
147
        return result;
148
    }
149

    
150
    private String addPages(String result, Reference reference) {
151
        //pages
152
        if (isNotBlank(reference.getPages())){
153
            //Removing trailing added just in case, maybe not necessary
154
            result = removeTrailingDots(result).trim() + ": " + reference.getPages();
155
        }
156
        return result;
157
    }
158

    
159
    @Override
160
    public String getNomenclaturalTitleCache(Reference reference) {
161
        if (reference == null){
162
            return null;
163
        }else{
164
            String refStr = nomSourceFormatter.format(reference, null);
165
            TeamOrPersonBase<?> authorTeam = reference.getAuthorship();
166
            String authorStr = authorTeam == null? null : authorTeam.getNomenclaturalTitle();
167
            String sep = refStr.startsWith("in ")? " ": ", ";
168
            return CdmUtils.concat(sep, authorStr, refStr);
169
        }
170
    }
171

    
172
    @Override
173
    public String getFullAbbrevTitleString(Reference reference) {
174
        if (reference == null){
175
            return null;
176
        }
177
        String result;
178
        ReferenceType type = reference.getType();
179
        boolean isAbbrev = true;
180

    
181
        if (reference.isProtectedAbbrevTitleCache()){
182
            return reference.getAbbrevTitleCache();
183
        }
184

    
185
        if (type == ReferenceType.Article){
186
            result = getTitleWithoutYearAndAuthor(reference, isAbbrev, false);
187
            boolean useFullDatePublished = false;
188
            String authorAndYear = getAuthorAndYear(reference, isAbbrev, useFullDatePublished);
189
            if (isNotBlank(authorAndYear)){
190
//                String authorSeparator = isNotBlank(reference.getTitle())? afterAuthor : " ";
191
                String authorSeparator = afterAuthor;
192
                authorAndYear += authorSeparator;
193
            }
194
            result = authorAndYear + result;
195
        }else if (isRealInRef(reference)){
196
            result = titleCacheRealInRef(reference, isAbbrev);
197
        }else if (isNomRef(type)){
198
            String authorAndYear = getAuthorAndYear(reference, isAbbrev, false);
199
            String title = getTitleWithoutYearAndAuthor(reference, isAbbrev, false);
200
            result = addPages(title, reference);
201
            //if Book, CdDvd, flat Generic, Thesis, WebPage
202
            if (isNotBlank(authorAndYear)){
203
                String authorSeparator = isNotBlank(title)? afterAuthor : "";
204
                authorAndYear += authorSeparator;
205
            }
206
            result = authorAndYear + result;
207
        }else if(type == ReferenceType.Journal){
208
            result = titleCacheJournal(reference, isAbbrev);
209
        }else{
210
            result = titleCacheDefaultReference(reference, isAbbrev);
211
        }
212

    
213
        return result;
214
    }
215

    
216
// ************************ TITLE CACHE SUBS ********************************************/
217

    
218
    //section, book section or generic with inRef
219
    private String titleCacheRealInRef(Reference reference, boolean isAbbrev) {
220

    
221
        Reference inRef = reference.getInReference();
222

    
223
        String inRefPart = getInRefAuthorAndTitle(inRef, reference.getType(), isAbbrev);
224
        if (inRef != null && !inRef.isArticle()){
225
            inRefPart = addInRefPages(inRef, inRefPart);
226
            if (inRef.isJournal()){
227
                inRefPart = addSeriesAndVolume(reference, inRefPart, isAbbrev);  //usually only needed for journals
228
            }
229
        }
230
        inRefPart = biblioInSeparator + inRefPart;
231
        if (inRef != null && inRef.isBookSection()){
232
            inRefPart = CdmUtils.addTrailingDotIfNotExists(inRefPart);
233
            String inInRefPart = getInRefAuthorAndTitle(inRef.getInReference(), inRef.getType(), isAbbrev);
234
            inInRefPart = biblioInSeparator + inInRefPart;
235
            inRefPart += inInRefPart;
236
        }
237

    
238
        //section title
239
        String title = CdmUtils.getPreferredNonEmptyString(
240
                reference.getTitle(), reference.getAbbrevTitle(), isAbbrev, trim);
241
        if (title.matches(".*[.!\\?]")){
242
            title = title.substring(0, title.length() - 1);
243
        }
244
        //pages
245
        title = addInRefPages(reference, title);
246

    
247
        String result;
248
        if (title.length() > 0){
249
            result = title.trim() + "." + inRefPart;
250
        }else{
251
            result = inRefPart;
252
        }
253

    
254
        //section author
255
        TeamOrPersonBase<?> author = reference.getAuthorship();
256
        String authorStr = (author == null)? "" : CdmUtils.getPreferredNonEmptyString(author.getTitleCache(),
257
                author.getNomenclaturalTitle(), isAbbrev, trim);
258

    
259
        //date
260
        String dateStr = null;
261
        VerbatimTimePeriod date = reference.hasDatePublished() ? reference.getDatePublished() : null;
262
        if (date == null && inRef != null && inRef.hasDatePublished()){
263
            date = reference.getInReference().getDatePublished();
264
            if (date == null && inRef.isSection() && inRef.getInReference() != null && inRef.getInReference().hasDatePublished()){
265
                date = inRef.getInReference().getDatePublished();
266
            }
267
        }
268
        if (date != null){
269
            dateStr = date.getYear();
270
        }
271

    
272
        String authorAndYear = CdmUtils.concat(" ", authorStr, dateStr);
273

    
274
        String sep = result.startsWith(biblioInSeparator)? "": afterAuthor;
275
        result = CdmUtils.concat(sep, authorAndYear, result);
276

    
277
        return result;
278
    }
279

    
280
    //copied from TitleWithoutYearAndAuthor.getTitleWithoutYearAndAuthorArticle
281
    //may be somehow merged in future
282
    private String addSeriesAndVolume(Reference ref, String inRefPart, boolean isAbbrev) {
283
        String series = Nz(ref.getSeriesPart()).trim();
284
        String volume = Nz(ref.getVolume()).trim();
285

    
286
        String inRefTitle = ReferenceDefaultCacheStrategy.UNDEFINED_JOURNAL;
287
        boolean needsComma = false;
288
        Reference inRef = ref.getInReference();
289
        if (inRef != null){
290
            inRefTitle = CdmUtils.getPreferredNonEmptyString(inRef.getTitle(), inRef.getAbbrevTitle(), isAbbrev, true);
291
            if (isNotBlank(inRefTitle)){
292
                needsComma = TitleWithoutYearAndAuthorHelper.computeNeedsCommaArticle(inRefPart, volume, series);
293
                if (! needsComma && (isNotBlank(volume)||isNotBlank(series))){
294
                    inRefPart += blank;
295
                }
296
            }
297
        }
298
        inRefPart = TitleWithoutYearAndAuthorHelper.getSeriesAndVolPartArticle(series, volume, needsComma, inRefPart);
299

    
300
        //delete "."
301
        while (inRefPart.endsWith(".")){
302
            inRefPart = CdmUtils.removeTrailingDots(inRefPart);
303
        }
304
        return inRefPart;
305
    }
306

    
307
    private String addInRefPages(Reference reference, String title) {
308
        String pages = getPages(reference);
309
        if (isNotBlank(pages)){
310
            title = CdmUtils.concat(", ", title, pages);
311
        }
312
        return title;
313
    }
314

    
315
    private String getInRefAuthorAndTitle(Reference inRef, ReferenceType type, boolean isAbbrev) {
316
        String inRefAuthorAndTitle;
317
        if (inRef != null){
318
            String inRefTitle = TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthor(inRef, isAbbrev, false);
319
            TeamOrPersonBase<?> inRefAuthor = inRef.getAuthorship();
320
            String authorStr = (inRefAuthor == null)? "" : CdmUtils.getPreferredNonEmptyString(inRefAuthor.getTitleCache(),
321
                    inRefAuthor.getNomenclaturalTitle(), isAbbrev, trim);
322
            inRefAuthorAndTitle = CdmUtils.concat(afterInRefAuthor, authorStr, inRefTitle);
323
        }else{
324
            inRefAuthorAndTitle = String.format("- undefined %s -", getUndefinedLabel(type));
325
        }
326

    
327
        return inRefAuthorAndTitle;
328
    }
329

    
330
    private static final String pageNoRe = "[0-9iIvVxXlLcCdDmM]+";
331
    private String getPages(Reference reference) {
332

    
333
        if (reference == null || isBlank(reference.getPages())){
334
            return null;
335
        }else if (reference.getPages().matches(pageNoRe + "\\s*[-"+UTF8.EN_DASH+"]\\s*"+ pageNoRe)){
336
            return "pp. " + reference.getPages();
337
        }else if (reference.getPages().matches(pageNoRe)){
338
            return "p. " + reference.getPages();
339
        }else{
340
            return reference.getPages();
341
        }
342
    }
343

    
344
    private String titleCacheJournal(Reference reference, boolean isAbbrev) {
345
        String result;
346
        //copied from Journal
347

    
348
        //title
349
        result = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
350
                reference.getAbbrevTitle(), isAbbrev, trim);
351

    
352
//          //delete .
353
//          while (result.endsWith(".")){
354
//              result = result.substring(0, result.length()-1);
355
//          }
356
//          result = addYear(result, journal);
357

    
358
        TeamOrPersonBase<?> team = reference.getAuthorship();
359
        if (team != null){
360
            String author = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
361
                    team.getNomenclaturalTitle(), isAbbrev, trim);
362
            if (isNotBlank(author)){
363
                result = author + afterAuthor + result;
364
            }
365
        }
366
        return result;
367
    }
368

    
369
    private String titleCacheDefaultReference(Reference reference, boolean isAbbrev) {
370
        String result;
371
        //copied from ReferenceDefaultCacheStrategy
372
        result = "";
373
        String titel = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
374
                reference.getAbbrevTitle(), isAbbrev, trim);
375
        if (isNotBlank(titel)){
376
            result = titel + blank;
377
        }
378
        //delete .
379
        while (result.endsWith(".")){
380
            result = result.substring(0, result.length()-1);
381
        }
382

    
383
        result = addYearReferenceDefault(result, reference);
384
        TeamOrPersonBase<?> team = reference.getAuthorship();
385
        if (team != null){
386
            String author = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
387
                    team.getNomenclaturalTitle(), isAbbrev, trim);
388
            if (isNotBlank(author)){
389
                result = author + afterAuthor + result;
390
            }
391
        }
392
        return result;
393
    }
394

    
395
// ******************************* HELPER *****************************************/
396

    
397
    /**
398
     * Adds the year or full date of a reference to a given string
399
     * @param currentStr the given string
400
     * @param reference the reference
401
     * @param useFullDatePublished wether to add the year only or the full date
402
     * @return the concatenated string
403
     */
404
    public static String addYear(String currentStr, Reference reference, boolean useFullDatePublished){
405
        String result;
406
        if (currentStr == null){
407
            return null;
408
        }
409
        String year = useFullDatePublished ? reference.getDatePublishedString() : reference.getYear();
410
        if (isBlank(year)){
411
            result = currentStr + afterYear;
412
        }else{
413
            String concat = isBlank(currentStr)  ? "" : currentStr.endsWith(".")  ? " " : beforeYear;
414
            result = currentStr + concat + year + afterYear;
415
        }
416
        return result;
417
    }
418

    
419
    private String addAuthorYear(String authorStr, Reference reference, boolean useFullDatePublished){
420
        String year = useFullDatePublished ? reference.getDatePublishedString() : reference.getYear();
421
        if (isBlank(year)){
422
            return authorStr;
423
        }else{
424
            return CdmUtils.concat(" ", authorStr, year);
425
        }
426
    }
427

    
428
    private String getTitleWithoutYearAndAuthor(Reference ref, boolean isAbbrev, boolean isNomRef){
429
        return TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthor(ref, isAbbrev, isNomRef);
430
    }
431

    
432
    private Object getUndefinedLabel(ReferenceType type) {
433
        if (type == ReferenceType.BookSection){
434
            return "book";
435
        }else if (type == ReferenceType.Generic){
436
            return "generic reference";
437
        }else if (type == ReferenceType.Section){
438
            return "in-reference";
439
        } else {
440
            return "in-reference for " + type.getLabel();
441
        }
442
    }
443

    
444
    /**
445
     * Returns <code>true</code> if the type of the reference originally corresponded to a cache strategy
446
     * which inherited from {@link InRefDefaultCacheStrategyBase} and in case of type {@link ReferenceType#Generic}
447
     * if it really has an inreference (reference.getInreference() != null).
448
     * @param reference
449
     */
450
    public static boolean isRealInRef(Reference reference) {
451
        ReferenceType type = (reference.getType());
452
        if (type == null){
453
            return false;
454
        }else if (type == ReferenceType.BookSection || type == ReferenceType.Section){
455
            return true;
456
        }else if (type == ReferenceType.Generic){
457
            return reference.getInReference() != null;
458
        }else{
459
            return false;
460
        }
461
    }
462

    
463
    /**
464
     * Returns <code>true</code> if the type of the reference originally corresponded to a cache strategy
465
     * which inherited from {@link NomRefDefaultCacheStrategyBase}.
466
     * @param type
467
     * @see ReferenceType#isNomRef()
468
     */
469
    public static boolean isNomRef(ReferenceType type){
470
        return type == null ? false : type.isNomRef();
471
    }
472

    
473
    /**
474
     * Returns year information as originally computed by {@link ReferenceDefaultCacheStrategy}.
475
     */
476
    private String addYearReferenceDefault(String string, Reference ref){
477
        String result;
478
        if (string == null){
479
            return null;
480
        }
481
        String year = CdmUtils.Nz(ref.getYear());
482
        if ("".equals(year)){
483
            result = string + afterYear;
484
        }else{
485
            result = string.trim() + beforeYear + year + afterYear;
486
        }
487
        return result;
488
    }
489

    
490
// *************************** EXTERNAL USE *******************************************/
491

    
492
   public static String putAuthorToEndOfString(String referenceTitle, String authorTitle) {
493
       if(authorTitle != null){
494
           referenceTitle = referenceTitle.replace(authorTitle + ", ", "");
495
           referenceTitle += " - " + authorTitle;
496
       }
497
       return referenceTitle;
498
   }
499
}
(2-2/3)