Project

General

Profile

Download (18.5 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
// ************************ FACTORY ****************************/
77

    
78
    public static ReferenceDefaultCacheStrategy NewInstance(){
79
        return new ReferenceDefaultCacheStrategy();
80
    }
81

    
82
// ******************************* Main methods ******************************/
83

    
84
    @Override
85
    protected UUID getUuid() {
86
        return uuid;
87
    }
88

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

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

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

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

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

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

    
160
    @Override
161
    public String getFullAbbrevTitleString(Reference reference) {
162
        if (reference == null){
163
            return null;
164
        }
165
        String result;
166
        ReferenceType type = reference.getType();
167
        boolean isAbbrev = true;
168

    
169
        if (reference.isProtectedAbbrevTitleCache()){
170
            return reference.getAbbrevTitleCache();
171
        }
172

    
173
        if (type == ReferenceType.Article){
174
            result = getTitleWithoutYearAndAuthor(reference, isAbbrev, false);
175
            boolean useFullDatePublished = false;
176
            String authorAndYear = getAuthorAndYear(reference, isAbbrev, useFullDatePublished);
177
            if (isNotBlank(authorAndYear)){
178
//                String authorSeparator = isNotBlank(reference.getTitle())? afterAuthor : " ";
179
                String authorSeparator = afterAuthor;
180
                authorAndYear += authorSeparator;
181
            }
182
            result = authorAndYear + result;
183
            result = CdmUtils.addTrailingDotIfNotExists(result);
184
        }else if (isRealInRef(reference)){
185
            result = titleCacheRealInRef(reference, isAbbrev);
186
        }else if (isNomRef(type)){
187
            String authorAndYear = getAuthorAndYear(reference, isAbbrev, false);
188
            String title = getTitleWithoutYearAndAuthor(reference, isAbbrev, false);
189
            result = addPages(title, reference);
190
            //if Book, CdDvd, flat Generic, Thesis, WebPage
191
            if (isNotBlank(authorAndYear)){
192
                String authorSeparator = isNotBlank(title)? afterAuthor : "";
193
                authorAndYear += authorSeparator;
194
            }
195
            result = authorAndYear + result;
196

    
197
            if (!type.isWebPage()){
198
                result = CdmUtils.addTrailingDotIfNotExists(result);
199
            }
200
        }else if(type == ReferenceType.Journal){
201
            result = titleCacheJournal(reference, isAbbrev);
202
        }else{
203
            result = titleCacheDefaultReference(reference, isAbbrev);
204
        }
205

    
206
        return result;
207
    }
208

    
209
// ************************ TITLE CACHE SUBS ********************************************/
210

    
211
    //section, book section or generic with inRef
212
    private String titleCacheRealInRef(Reference reference, boolean isAbbrev) {
213

    
214
        Reference inRef = reference.getInReference();
215

    
216
        String inRefPart = getInRefAuthorAndTitle(inRef, reference.getType(), isAbbrev);
217
        if (inRef != null && !inRef.isArticle()){
218
            inRefPart = addInRefPages(inRef, inRefPart);
219
        }
220
        inRefPart = CdmUtils.addTrailingDotIfNotExists(inRefPart);
221
        inRefPart = biblioInSeparator + inRefPart;
222
        if (inRef != null && inRef.isBookSection()){
223
            String inInRefPart = getInRefAuthorAndTitle(inRef.getInReference(), inRef.getType(), isAbbrev);
224
            inInRefPart = CdmUtils.addTrailingDotIfNotExists(inInRefPart);
225
            inInRefPart = biblioInSeparator + inInRefPart;
226
            inRefPart += inInRefPart;
227
        }
228

    
229
        //section title
230
        String title = CdmUtils.getPreferredNonEmptyString(
231
                reference.getTitle(), reference.getAbbrevTitle(), isAbbrev, trim);
232
        if (title.matches(".*[.!\\?]")){
233
            title = title.substring(0, title.length() - 1);
234
        }
235
        //pages
236
        title = addInRefPages(reference, title);
237

    
238
        String result;
239
        if (title.length() > 0){
240
            result = title.trim() + "." + inRefPart;
241
        }else{
242
            result = inRefPart;
243
        }
244

    
245
        //section author
246
        TeamOrPersonBase<?> author = reference.getAuthorship();
247
        String authorStr = (author == null)? "" : CdmUtils.getPreferredNonEmptyString(author.getTitleCache(),
248
                author.getNomenclaturalTitle(), isAbbrev, trim);
249

    
250
        //date
251
        String dateStr = null;
252
        VerbatimTimePeriod date = reference.hasDatePublished() ? reference.getDatePublished() : null;
253
        if (date == null && inRef != null && inRef.hasDatePublished()){
254
            date = reference.getInReference().getDatePublished();
255
            if (date == null && inRef.isSection() && inRef.getInReference() != null && inRef.getInReference().hasDatePublished()){
256
                date = inRef.getInReference().getDatePublished();
257
            }
258
        }
259
        if (date != null){
260
            dateStr = date.getYear();
261
        }
262

    
263
        String authorAndYear = CdmUtils.concat(" ", authorStr, dateStr);
264

    
265
        String sep = result.startsWith(biblioInSeparator)? "": afterAuthor;
266
        result = CdmUtils.concat(sep, authorAndYear, result);
267

    
268
        return result;
269
    }
270

    
271
    private String addInRefPages(Reference reference, String title) {
272
        String pages = getPages(reference);
273
        if (isNotBlank(pages)){
274
            title = CdmUtils.concat(", ", title, pages);
275
        }
276
        return title;
277
    }
278

    
279
    private String getInRefAuthorAndTitle(Reference inRef, ReferenceType type, boolean isAbbrev) {
280
        String inRefAuthorAndTitle;
281
        if (inRef != null){
282
            String inRefTitle = TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthor(inRef, isAbbrev, false);
283
            TeamOrPersonBase<?> inRefAuthor = inRef.getAuthorship();
284
            String authorStr = (inRefAuthor == null)? "" : CdmUtils.getPreferredNonEmptyString(inRefAuthor.getTitleCache(),
285
                    inRefAuthor.getNomenclaturalTitle(), isAbbrev, trim);
286
            inRefAuthorAndTitle = CdmUtils.concat(afterInRefAuthor, authorStr, inRefTitle);
287
        }else{
288
            inRefAuthorAndTitle = String.format("- undefined %s -", getUndefinedLabel(type));
289
        }
290

    
291
        return inRefAuthorAndTitle;
292
    }
293

    
294
    private static final String pageNoRe = "[0-9iIvVxXlLcCdDmM]+";
295
    private String getPages(Reference reference) {
296

    
297
        if (reference == null || isBlank(reference.getPages())){
298
            return null;
299
        }else if (reference.getPages().matches(pageNoRe + "\\s*[-"+UTF8.EN_DASH+"]\\s*"+ pageNoRe)){
300
            return "pp. " + reference.getPages();
301
        }else if (reference.getPages().matches(pageNoRe)){
302
            return "p. " + reference.getPages();
303
        }else{
304
            return reference.getPages();
305
        }
306
    }
307

    
308
    private String titleCacheJournal(Reference reference, boolean isAbbrev) {
309
        String result;
310
        //copied from Journal
311

    
312
        //title
313
        result = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
314
                reference.getAbbrevTitle(), isAbbrev, trim);
315

    
316
//          //delete .
317
//          while (result.endsWith(".")){
318
//              result = result.substring(0, result.length()-1);
319
//          }
320
//          result = addYear(result, journal);
321

    
322
        TeamOrPersonBase<?> team = reference.getAuthorship();
323
        if (team != null){
324
            String author = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
325
                    team.getNomenclaturalTitle(), isAbbrev, trim);
326
            if (isNotBlank(author)){
327
                result = author + afterAuthor + result;
328
            }
329
        }
330
        return result;
331
    }
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

    
361
    /**
362
     * Adds the year or full date of a reference to a given string
363
     * @param currentStr the given string
364
     * @param reference the reference
365
     * @param useFullDatePublished wether to add the year only or the full date
366
     * @return the concatenated string
367
     */
368
    public static String addYear(String currentStr, Reference reference, boolean useFullDatePublished){
369
        String result;
370
        if (currentStr == null){
371
            return null;
372
        }
373
        String year = useFullDatePublished ? reference.getDatePublishedString() : reference.getYear();
374
        if (isBlank(year)){
375
            result = currentStr + afterYear;
376
        }else{
377
            String concat = isBlank(currentStr)  ? "" : currentStr.endsWith(".")  ? " " : beforeYear;
378
            result = currentStr + concat + year + afterYear;
379
        }
380
        return result;
381
    }
382

    
383
    private String addAuthorYear(String authorStr, Reference reference, boolean useFullDatePublished){
384
        String year = useFullDatePublished ? reference.getDatePublishedString() : reference.getYear();
385
        if (isBlank(year)){
386
            return authorStr;
387
        }else{
388
            return CdmUtils.concat(" ", authorStr, year);
389
        }
390
    }
391

    
392
    private String getTitleWithoutYearAndAuthor(Reference ref, boolean isAbbrev, boolean isNomRef){
393
        return TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthor(ref, isAbbrev, isNomRef);
394
    }
395

    
396
    private Object getUndefinedLabel(ReferenceType type) {
397
        if (type == ReferenceType.BookSection){
398
            return "book";
399
        }else if (type == ReferenceType.Generic){
400
            return "generic reference";
401
        }else if (type == ReferenceType.Section){
402
            return "in-reference";
403
        } else {
404
            return "in-reference for " + type.getLabel();
405
        }
406
    }
407

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

    
427
    /**
428
     * Returns <code>true</code> if the type of the reference originally corresponded to a cache strategy
429
     * which inherited from {@link NomRefDefaultCacheStrategyBase}.
430
     * @param type
431
     * @see ReferenceType#isNomRef()
432
     */
433
    public static boolean isNomRef(ReferenceType type){
434
        return type == null ? false : type.isNomRef();
435
    }
436

    
437
    /**
438
     * Returns year information as originally computed by {@link ReferenceDefaultCacheStrategy}.
439
     */
440
    private String addYearReferenceDefault(String string, Reference ref){
441
        String result;
442
        if (string == null){
443
            return null;
444
        }
445
        String year = CdmUtils.Nz(ref.getYear());
446
        if ("".equals(year)){
447
            result = string + afterYear;
448
        }else{
449
            result = string.trim() + beforeYear + year + afterYear;
450
        }
451
        return result;
452
    }
453

    
454
// *************************** EXTERNAL USE *******************************************/
455

    
456
   public static String putAuthorToEndOfString(String referenceTitle, String authorTitle) {
457
       if(authorTitle != null){
458
           referenceTitle = referenceTitle.replace(authorTitle + ", ", "");
459
           referenceTitle += " - " + authorTitle;
460
       }
461
       return referenceTitle;
462
   }
463
}
(2-2/3)