Project

General

Profile

Download (12.6 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2021 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.format.reference;
10

    
11
import org.apache.log4j.Logger;
12

    
13
import eu.etaxonomy.cdm.common.CdmUtils;
14
import eu.etaxonomy.cdm.format.CdmFormatterBase;
15
import eu.etaxonomy.cdm.model.agent.Person;
16
import eu.etaxonomy.cdm.model.agent.Team;
17
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
18
import eu.etaxonomy.cdm.model.common.CdmBase;
19
import eu.etaxonomy.cdm.model.name.NomenclaturalSource;
20
import eu.etaxonomy.cdm.model.name.TaxonName;
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.cache.agent.TeamDefaultCacheStrategy;
25
import eu.etaxonomy.cdm.strategy.cache.reference.ReferenceDefaultCacheStrategy;
26
import eu.etaxonomy.cdm.strategy.cache.reference.TitleWithoutYearAndAuthorHelper;
27

    
28
/**
29
 * @author a.mueller
30
 * @since 03.05.2021
31
 */
32
public class NomenclaturalSourceFormatter extends CdmFormatterBase<NomenclaturalSource>{
33

    
34
    private static final Logger logger = Logger.getLogger(NomenclaturalSourceFormatter.class);
35

    
36
    private static final String beforeMicroReference = ": ";
37
    private static final String afterInRefAuthor = ", ";
38

    
39
    private static NomenclaturalSourceFormatter instance;
40

    
41
    public static final NomenclaturalSourceFormatter INSTANCE() {
42
            if (instance == null){
43
                instance = new NomenclaturalSourceFormatter();
44
            }
45
            return instance;
46
    }
47

    
48
    @Override
49
    public String format(NomenclaturalSource source){
50
        if (source == null){
51
            return null;
52
        }
53
        Reference reference = source.getCitation();
54
        String microReference = source.getCitationMicroReference();
55
        if (reference == null && isBlank(microReference)){
56
            return null;
57
        }
58
        return format(reference, microReference);
59
    }
60

    
61
    /**
62
    * Returns a formatted string containing the entire citation used for
63
    * nomenclatural purposes based on the {@link Reference reference} supplied - including
64
    * (abbreviated) title  but not authors - and on the given details.<BR>
65
    *
66
    * @param  reference
67
    *                         the nomenclatural reference
68
    * @param  microReference  the string with the details (generally pages)
69
    *                         corresponding to the nomenclatural reference supplied
70
    *                         as the first argument
71
    * @return                 the formatted string representing the
72
    *                         nomenclatural citation
73
    * @see                    INomenclaturalReference#getNomenclaturalCitation(String)
74
    * @see                    TaxonName#getNomenclaturalReference()
75
    */
76
    public String format(Reference reference, String microReference){
77
        if (reference == null){
78
            return CdmUtils.concat(beforeMicroReference, "-", microReference);
79
        }
80

    
81
        if (reference.isProtectedAbbrevTitleCache()){
82
            String cache = reference.getAbbrevTitleCache();
83
            return handleDetailAndYearForProtected(reference, cache, microReference);
84
        }
85

    
86
        String result = getTokenizedNomenclaturalTitel(reference);
87
        //if no data is available and only titleCache is protected take the protected title
88
        //this is to avoid empty cache if someone forgets to set also the abbrevTitleCache
89
        //we need to think about handling protected not separate for abbrevTitleCache  and titleCache
90
        if (result.equals(INomenclaturalReference.MICRO_REFERENCE_TOKEN) && reference.isProtectedTitleCache() ){
91
            String cache = reference.getTitleCache();
92
            return handleDetailAndYearForProtected(reference, cache, microReference);
93
        }
94

    
95
        microReference = Nz(microReference);
96
        if (isNotBlank(microReference)){
97
            microReference = getBeforeMicroReference() + microReference;
98
            if (microReference.endsWith(".")  && result.contains(INomenclaturalReference.MICRO_REFERENCE_TOKEN + ".") ){
99
                microReference = microReference.substring(0, microReference.length() - 1);
100
            }
101
        }
102
        result = replaceMicroRefToken(microReference, result);
103
        if (result.startsWith(". ")){  //only year available, remove '. '
104
            result = result.substring(2);
105
        }
106
        return result;
107
    }
108

    
109
    private String getBeforeMicroReference(){
110
        return beforeMicroReference;
111
    }
112

    
113
    /**
114
     * Returns the nomenclatural title with micro reference represented as token
115
     * which can later be replaced by the real data.
116
     *
117
     * @see INomenclaturalReference#MICRO_REFERENCE_TOKEN
118
     */
119
    private String getTokenizedNomenclaturalTitel(Reference ref) {
120
        if (ReferenceDefaultCacheStrategy.isRealInRef(ref)){
121
            return getTokenizedNomenclaturalTitelInRef(ref);
122
        }else{
123
            String result = getTitleWithoutYearAndAuthor(ref, true, true);
124
            result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
125
            result = addYear(result, ref, true);
126
            return result;
127
        }
128
    }
129

    
130
    private String replaceMicroRefToken(String microReference, String string) {
131
        int index = string.indexOf(INomenclaturalReference.MICRO_REFERENCE_TOKEN);
132

    
133
        if (index > -1){
134
            String before = string.substring(0, index);
135
            String after = string.substring(index + INomenclaturalReference.MICRO_REFERENCE_TOKEN.length() );
136
            String localMicroReference = microReference.trim();   //needed ?
137
            if (after.length() > 0){
138
                if (  ("".equals(localMicroReference) && before.endsWith(after.substring(0,1)) || localMicroReference.endsWith(after.substring(0,1)))){
139
                    after = after.substring(1);
140
                }
141
            }
142
            String result = before + localMicroReference + after;
143
            return result;
144
        }else{
145
            return string;
146
        }
147
    }
148

    
149
    private String handleDetailAndYearForProtected(Reference nomenclaturalReference, String cache, String microReference) {
150
        String microRef = isNotBlank(microReference) ? getBeforeMicroReference() + microReference : "";
151
        if (cache == null){
152
            logger.warn("Cache is null. This should never be the case.");
153
            cache = "";
154
        }
155
        String  result = cache + (cache.contains(microRef) ? "" : microRef);
156

    
157
        String date = nomenclaturalReference.getDatePublishedString();
158
        if (isNotBlank(date) && ! result.contains(date)){
159
            result = result + ReferenceDefaultCacheStrategy.beforeYear + date;
160
        }
161
        return result;
162
    }
163

    
164
    private String getTokenizedNomenclaturalTitelInRef(Reference thisRef) {
165
        if (thisRef == null){
166
            return null;
167
        }
168

    
169
        Reference inRef = CdmBase.deproxy(thisRef.getInReference());
170
        if (inRef != null && inRef.getInReference() != null && thisRef.getType() == ReferenceType.Section){
171
            //this is a reference of type Section which has an in-in-Ref
172
            //TODO maybe we do not need to restrict to type=Section only
173
            return this.getTokenizedNomenclaturalTitelInInRef(thisRef);
174
        }
175

    
176
        String result;
177
        //use generics's publication date if it exists
178
        if (inRef == null ||  (thisRef.hasDatePublished() ) ){
179
            result =  inRef == null ? "" : getTitleWithoutYearAndAuthorGeneric(inRef, true);
180
            //added //TODO unify with non-inRef references formatting
181

    
182
            if (isNotBlank(thisRef.getVolume())){
183
                result = result + " " + thisRef.getVolume();
184
            }
185
            //TODO series / edition
186

    
187
            //end added
188
            result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
189
            result = addYear(result, thisRef, true);
190
        }else{
191
            //else use inRefs's publication date
192
            result = inRef.getNomenclaturalCitation(INomenclaturalReference.MICRO_REFERENCE_TOKEN);
193
            if (result != null){
194
                result = result.replace(beforeMicroReference +  INomenclaturalReference.MICRO_REFERENCE_TOKEN, INomenclaturalReference.MICRO_REFERENCE_TOKEN);
195
            }
196
        }
197
        //FIXME: vol. etc., https://dev.e-taxonomy.eu/redmine/issues/2862
198

    
199
        result = getInRefAuthorPart(thisRef.getInReference(), afterInRefAuthor) + result;
200
        result = "in " +  result;
201
        return result;
202
    }
203

    
204

    
205
    /**
206
     * For handling in-in-Ref case.
207
     * Must only be called if a reference has inRef and inInRef
208
     * @param section
209
     * @return
210
     */
211
    private String getTokenizedNomenclaturalTitelInInRef(Reference ref) {
212
        String result;
213

    
214
        Reference inRef = CdmBase.deproxy(ref.getInReference());
215
        Reference inInRef = CdmBase.deproxy(inRef.getInReference());
216

    
217
        if (! ReferenceDefaultCacheStrategy.isNomRef(inInRef.getType())){
218
            if (! ReferenceDefaultCacheStrategy.isNomRef(inRef.getType())){
219
                logger.warn("Neither inReference nor inInReference is a "
220
                        + " nomenclatural reference. This is not correct or not handled yet."
221
                        + " Generic titleWithoutYearAndAuthor used instead");
222
                result = getTitleWithoutYearAndAuthorGeneric(inInRef, true);
223
                //FIXME: vol. etc., https://dev.e-taxonomy.eu/redmine/issues/2862  (comment taken from super.getTokenizedNomenclaturalTitel())
224
            }else{
225
                result = getTitleWithoutYearAndAuthor(inRef, true, true);
226
            }
227
        }else{
228
            result = getTitleWithoutYearAndAuthor(inInRef, true, true);
229
        }
230
        result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
231

    
232
        Reference dataReference = (ref.hasDatePublished() ? ref : inRef.hasDatePublished() ? inRef : inInRef);
233

    
234
        result = addYear(result, dataReference, true);
235

    
236
        result = getInRefAuthorPart(inInRef, afterInRefAuthor) + result;
237
        if (! result.startsWith("in ")){
238
            result = "in " +  result;
239
        }
240
        return result;
241
    }
242

    
243
    /**
244
     * See https://dev.e-taxonomy.eu/redmine/issues/8881
245
     */
246
    private String getInRefAuthorPart(Reference book, String seperator){
247
        if (book == null){
248
            return "";
249
        }
250

    
251
        TeamOrPersonBase<?> author = book.getAuthorship();
252
        String result;
253
        if (author == null){
254
            result = "";
255
        }else if(author.isInstanceOf(Person.class)){
256
            Person person = CdmBase.deproxy(author, Person.class);
257
            result = getInRefPerson(person);
258
        }else{
259
            Team team = CdmBase.deproxy(author, Team.class);
260
            if (team.isProtectedNomenclaturalTitleCache()){
261
                //not yet finally discussed may change in future
262
                result = team.getNomenclaturalTitle();
263
            }else if (team.isProtectedTitleCache()){
264
                //not yet finally discussed may change in future
265
                result = team.getTitleCache();
266
            }else if (team.getTeamMembers().isEmpty()){
267
                //not yet finally discussed may change in future
268
                result = team.getTitleCache();
269
            }else{
270
                result = TeamDefaultCacheStrategy.INSTANCE_ET_AL_3().getFamilyTitle(team);
271
            }
272
        }
273

    
274
        result = Nz(result);
275
        if (! result.trim().equals("")){
276
            result = result + seperator;
277
        }
278
        return result;
279
    }
280

    
281
    private String getInRefPerson(Person person) {
282
        String result;
283
        if (isNotBlank(person.getFamilyName())){
284
            result = person.getFamilyName();
285
        }else if (isNotBlank(person.getNomenclaturalTitle())){
286
            result = person.getNomenclaturalTitle();  //TODO discuss if nomTitle is really better here then titleCache
287
        }else{
288
            result = person.getTitleCache();  //maybe remove everything behind a ","
289
        }
290
        return result;
291
    }
292

    
293
    /**
294
     * @see ReferenceDefaultCacheStrategy#addYear(String, Reference, boolean)
295
     */
296
    private String addYear(String yearStr, Reference ref, boolean useFullDatePublished) {
297
        return ReferenceDefaultCacheStrategy.addYear(yearStr, ref, useFullDatePublished);
298
    }
299
    private String getTitleWithoutYearAndAuthorGeneric(Reference ref, boolean isAbbrev){
300
        return TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthorGeneric(ref, isAbbrev);
301
    }
302
    private String getTitleWithoutYearAndAuthor(Reference ref, boolean isAbbrev, boolean isNomRef){
303
        return TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthor(ref, isAbbrev, isNomRef);
304
    }
305
}
(1-1/3)