Project

General

Profile

Download (12.7 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 java.io.Serializable;
12

    
13
import org.apache.log4j.Logger;
14

    
15
import eu.etaxonomy.cdm.common.CdmUtils;
16
import eu.etaxonomy.cdm.format.CdmFormatterBase;
17
import eu.etaxonomy.cdm.model.agent.Person;
18
import eu.etaxonomy.cdm.model.agent.Team;
19
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
20
import eu.etaxonomy.cdm.model.common.CdmBase;
21
import eu.etaxonomy.cdm.model.name.NomenclaturalSource;
22
import eu.etaxonomy.cdm.model.name.TaxonName;
23
import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
24
import eu.etaxonomy.cdm.model.reference.Reference;
25
import eu.etaxonomy.cdm.model.reference.ReferenceType;
26
import eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy;
27
import eu.etaxonomy.cdm.strategy.cache.reference.ReferenceDefaultCacheStrategy;
28
import eu.etaxonomy.cdm.strategy.cache.reference.TitleWithoutYearAndAuthorHelper;
29

    
30
/**
31
 * @author a.mueller
32
 * @since 03.05.2021
33
 */
34
public class NomenclaturalSourceFormatter
35
        extends CdmFormatterBase<NomenclaturalSource>
36
        implements Serializable {   //only required because used in ReferenceDefaultCacheStrategy
37

    
38
    private static final Logger logger = Logger.getLogger(NomenclaturalSourceFormatter.class);
39

    
40
    private static final String beforeMicroReference = ": ";
41
    private static final String afterInRefAuthor = ", ";
42

    
43
    private static NomenclaturalSourceFormatter instance;
44

    
45
    public static final NomenclaturalSourceFormatter INSTANCE() {
46
            if (instance == null){
47
                instance = new NomenclaturalSourceFormatter();
48
            }
49
            return instance;
50
    }
51

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

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

    
85
        if (reference.isProtectedAbbrevTitleCache()){
86
            String cache = reference.getAbbrevTitleCache();
87
            return handleDetailAndYearForProtected(reference, cache, microReference);
88
        }
89

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

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

    
113
    private String getBeforeMicroReference(){
114
        return beforeMicroReference;
115
    }
116

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

    
134
    private String replaceMicroRefToken(String microReference, String string) {
135
        int index = string.indexOf(INomenclaturalReference.MICRO_REFERENCE_TOKEN);
136

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

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

    
161
        String date = nomenclaturalReference.getDatePublishedString();
162
        if (isNotBlank(date) && ! result.contains(date)){
163
            result = result + ReferenceDefaultCacheStrategy.beforeYear + date;
164
        }
165
        return result;
166
    }
167

    
168
    private String getTokenizedNomenclaturalTitelInRef(Reference thisRef) {
169
        if (thisRef == null){
170
            return null;
171
        }
172

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

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

    
186
            if (isNotBlank(thisRef.getVolume())){
187
                result = result + " " + thisRef.getVolume();
188
            }
189
            //TODO series / edition
190

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

    
203
        result = getInRefAuthorPart(thisRef.getInReference(), afterInRefAuthor) + result;
204
        result = "in " +  result;
205
        return result;
206
    }
207

    
208

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

    
218
        Reference inRef = CdmBase.deproxy(ref.getInReference());
219
        Reference inInRef = CdmBase.deproxy(inRef.getInReference());
220

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

    
236
        Reference dataReference = (ref.hasDatePublished() ? ref : inRef.hasDatePublished() ? inRef : inInRef);
237

    
238
        result = addYear(result, dataReference, true);
239

    
240
        result = getInRefAuthorPart(inInRef, afterInRefAuthor) + result;
241
        if (! result.startsWith("in ")){
242
            result = "in " +  result;
243
        }
244
        return result;
245
    }
246

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

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

    
278
        result = Nz(result);
279
        if (! result.trim().equals("")){
280
            result = result + seperator;
281
        }
282
        return result;
283
    }
284

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

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