Project

General

Profile

Download (10.7 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2018 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.taxon;
10

    
11
import java.util.ArrayList;
12
import java.util.List;
13

    
14
import org.apache.commons.lang3.StringUtils;
15

    
16
import eu.etaxonomy.cdm.common.UTF8;
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.common.Language;
22
import eu.etaxonomy.cdm.model.name.TaxonName;
23
import eu.etaxonomy.cdm.model.reference.Reference;
24
import eu.etaxonomy.cdm.model.taxon.Taxon;
25
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
26
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
27
import eu.etaxonomy.cdm.model.term.Representation;
28
import eu.etaxonomy.cdm.ref.TypedEntityReference;
29
import eu.etaxonomy.cdm.strategy.cache.TagEnum;
30
import eu.etaxonomy.cdm.strategy.cache.TaggedText;
31
import eu.etaxonomy.cdm.strategy.cache.TaggedTextBuilder;
32
import eu.etaxonomy.cdm.strategy.cache.agent.PersonDefaultCacheStrategy;
33
import eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy;
34

    
35
/**
36
 * Formatter for TaxonRelationships.
37
 *
38
 * @author a.mueller
39
 * @since 13.08.2018
40
 */
41
public class TaxonRelationshipFormatter {
42

    
43
    private static final String DOUBTFUL_TAXON_MARKER = "?" + UTF8.NARROW_NO_BREAK;
44
    private static final String REL_SEC = ", rel. sec. ";
45
    private static final String ERR_SEC = ", err. sec. ";
46
    private static final String SYN_SEC = ", syn. sec. ";
47
    private static final String UNKNOWN_SEC = "???";
48
    private static final String NON_SEPARATOR = ", non ";
49
    private static final String QUOTE_START = "\"";   //TODO
50
    private static final String QUOTE_END = "\"";   //TODO
51
    private static final String AUCT = "auct.";
52
    private static final String SENSU_SEPARATOR = " sensu ";
53
    private static final String SEC_SEPARATOR = " sec. ";
54
    private static final String DETAIL_SEPARATOR = ": ";
55
    private static final String INVERT_SYMBOL = "<-"; //TODO
56
    private static final String UNDEFINED_SYMBOL = "??";  //TODO
57

    
58
    private static TaxonRelationshipFormatter instance;
59

    
60
    public static TaxonRelationshipFormatter NewInstance(){
61
        return new TaxonRelationshipFormatter();
62
    }
63

    
64
    public static TaxonRelationshipFormatter INSTANCE(){
65
        if (instance == null){
66
            instance = NewInstance();
67
        }
68
        return instance;
69
    }
70

    
71
    private TaxonRelationshipFormatter(){
72

    
73
    }
74

    
75
    public List<TaggedText> getTaggedText(TaxonRelationship taxonRelationship, boolean reverse, List<Language> languages) {
76
        return getTaggedText(taxonRelationship, reverse, languages, false);
77
    }
78

    
79
    public List<TaggedText> getTaggedText(TaxonRelationship taxonRelationship, boolean reverse,
80
            List<Language> languages, boolean withoutName) {
81

    
82
        if (taxonRelationship == null){
83
            return null;
84
        }
85

    
86
        TaxonRelationshipType type = taxonRelationship.getType();
87
        boolean isMisapplied = type == null ? false : type.isMisappliedName() && reverse;
88
        boolean isSynonym = type == null? false : type.isAnySynonym();
89

    
90
        Taxon relatedTaxon = reverse? taxonRelationship.getFromTaxon()
91
                : taxonRelationship.getToTaxon();
92

    
93
        if (relatedTaxon == null){
94
            return null;
95
        }
96

    
97
        String doubtfulTaxonStr = relatedTaxon.isDoubtful() ? DOUBTFUL_TAXON_MARKER : "";
98
        String doubtfulRelationStr = taxonRelationship.isDoubtful() ? "?" : "";
99

    
100
        TaxonName name = relatedTaxon.getName();
101

    
102
        TaggedTextBuilder builder = new TaggedTextBuilder();
103

    
104
        //rel symbol
105
        String symbol = doubtfulRelationStr + getSymbol(type, reverse, languages);
106
        builder.add(TagEnum.symbol, symbol);
107

    
108
        //name
109
        if (!withoutName){
110
            if (isMisapplied){
111
                //starting quote
112
                String startQuote = " " + doubtfulTaxonStr + QUOTE_START;
113
                builder.addSeparator(startQuote);
114

    
115
                //name cache
116
                List<TaggedText> nameCacheTags = getNameCacheTags(name);
117
                builder.addAll(nameCacheTags);
118

    
119
                //end quote
120
                String endQuote = QUOTE_END;
121
                builder.add(TagEnum.postSeparator, endQuote);
122
            }else{
123
                builder.addSeparator(" " + doubtfulTaxonStr);
124
                //name full title cache
125
                List<TaggedText> nameCacheTags = getNameTitleCacheTags(name);
126
                builder.addAll(nameCacheTags);
127
            }
128
        }else{
129
            if (isNotBlank(doubtfulTaxonStr)){
130
                builder.addSeparator(" " + doubtfulTaxonStr);
131
            }
132
        }
133

    
134
        //sec/sensu (+ Separatoren?)
135
        if (isNotBlank(relatedTaxon.getAppendedPhrase())){
136
            builder.addWhitespace();
137
            builder.add(TagEnum.appendedPhrase, relatedTaxon.getAppendedPhrase());
138
        }
139
        List<TaggedText> secTags = getReferenceTags(relatedTaxon.getSec(), relatedTaxon.getSecMicroReference(),
140
               /* isMisapplied,*/ false);
141
        if (!secTags.isEmpty()) {
142
            builder.addSeparator(isMisapplied? SENSU_SEPARATOR : SEC_SEPARATOR);
143
            builder.addAll(secTags);
144
        }else if (isBlank(relatedTaxon.getAppendedPhrase())) {
145
            if (isMisapplied){
146
                builder.addWhitespace();
147
                //TODO type unclear sensuReference(?)
148
                builder.add(TagEnum.appendedPhrase, AUCT);
149
            }else{
150
                builder.addSeparator(SEC_SEPARATOR + UNKNOWN_SEC);
151
            }
152
        }
153

    
154
//        //, non author
155
        if (isMisapplied && name != null){
156
            if (isNotBlank(name.getAuthorshipCache())){
157
                builder.addSeparator(NON_SEPARATOR);
158
                builder.add(TagEnum.authors, name.getAuthorshipCache().trim());
159
            }
160
        }
161

    
162
        List<TaggedText> relSecTags = getReferenceTags(taxonRelationship.getCitation(),
163
                taxonRelationship.getCitationMicroReference(),true);
164
        if (!relSecTags.isEmpty()){
165
            builder.addSeparator(isSynonym ? SYN_SEC : isMisapplied ? ERR_SEC : REL_SEC);
166
            builder.addAll(relSecTags);
167
        }
168

    
169
        return builder.getTaggedText();
170
    }
171

    
172
    private List<TaggedText> getReferenceTags(Reference ref, String detail, /*boolean isSensu,*/ boolean isRelation) {
173
        List<TaggedText> result = new ArrayList<>();
174
        String secRef;
175

    
176
        if (ref != null){
177
            TeamOrPersonBase<?> author = CdmBase.deproxy(ref.getAuthorship());
178

    
179
            //TODO distinguish linked and unlinked usage,
180
            // if reference is not linked short citation should only be used
181
            //   if both author and year exists, also initials should be added in this case
182
            //
183
            if (ref.isProtectedTitleCache() == false &&
184
                    author != null &&
185
                    isNotBlank(author.getTitleCache())){
186
                if (author.isInstanceOf(Person.class)){
187
                    secRef = PersonDefaultCacheStrategy.INSTANCE().getFamilyTitle((Person)author);
188
                }else{
189
                    //TODO this may become ET_AL_2 in future
190
                    secRef = TeamDefaultCacheStrategy.INSTANCE().getFamilyTitle((Team)author);
191
                }
192
                if (isNotBlank(ref.getYear())){
193
                   secRef += " " + ref.getYear();
194
                }
195
            }else{
196
                secRef = ref.getTitleCache();
197
            }
198
            TagEnum secType = /*isSensu? TagEnum.sensuReference : */ isRelation? TagEnum.relSecReference : TagEnum.secReference;
199
            TaggedText refTag = TaggedText.NewInstance(secType, secRef);
200
            refTag.setEntityReference(new TypedEntityReference<>(CdmBase.deproxy(ref).getClass(), ref.getUuid()));
201
            result.add(refTag);
202
        }
203
        if (isNotBlank(detail)){
204
            result.add(TaggedText.NewSeparatorInstance(DETAIL_SEPARATOR));
205
            TagEnum detailType = /*isSensu? TagEnum.sensuMicroReference : */ isRelation? TagEnum.relSecMicroReference :TagEnum.secMicroReference;
206
            TaggedText microTag = TaggedText.NewInstance(detailType, detail);
207
            result.add(microTag);
208
        }
209
        return result;
210
    }
211

    
212
    private List<TaggedText> getNameCacheTags(TaxonName name) {
213
        List<TaggedText> result = name.getCacheStrategy().getTaggedName(name);
214
        return result;
215
    }
216

    
217
    private List<TaggedText> getNameTitleCacheTags(TaxonName name) {
218

    
219
        //TODO full title?
220
        List<TaggedText> result = name.getCacheStrategy().getTaggedFullTitle(name);
221
        return result;
222
    }
223

    
224
    /**
225
     * @param type the taxon relationship type
226
     * @param reverse is the relationship used reverse
227
     * @param languages list of preferred languages
228
     * @return the symbol for the taxon relationship
229
     */
230
    private String getSymbol(TaxonRelationshipType type, boolean reverse, List<Language> languages) {
231
        if (type == null){
232
            return UNDEFINED_SYMBOL;
233
        }
234

    
235
        //symbol
236
        String symbol = reverse? type.getInverseSymbol():type.getSymbol();
237
        if (isNotBlank(symbol)){
238
            return symbol;
239
        }
240

    
241
        boolean isSymmetric = type.isSymmetric();
242
        //symmetric inverted symbol
243
        String invertedSymbol = reverse? type.getSymbol() : type.getInverseSymbol();
244
        if (isSymmetric && isNotBlank(invertedSymbol)){
245
            return invertedSymbol;
246
        }
247

    
248
        //abbrev label
249
        Representation representation = reverse? type.getPreferredRepresentation(languages): type.getPreferredInverseRepresentation(languages);
250
        String abbrevLabel = representation.getAbbreviatedLabel();
251
        if (isNotBlank(abbrevLabel)){
252
            return abbrevLabel;
253
        }
254

    
255
        //symmetric inverted abbrev label
256
        Representation invertedRepresentation = reverse? type.getPreferredInverseRepresentation(languages):type.getPreferredRepresentation(languages);
257
        String invertedAbbrevLabel = invertedRepresentation.getAbbreviatedLabel();
258
        if (isSymmetric && isNotBlank(invertedAbbrevLabel)){
259
            return invertedAbbrevLabel;
260
        }
261

    
262
        //non symmetric inverted symbol
263
        if (!isSymmetric && isNotBlank(invertedSymbol)){
264
            return INVERT_SYMBOL + invertedSymbol;
265
        }
266

    
267
        //non symmetric inverted abbrev label
268
        if (!isSymmetric && isNotBlank(invertedAbbrevLabel)){
269
            return INVERT_SYMBOL + invertedAbbrevLabel;
270
        }
271

    
272
        return UNDEFINED_SYMBOL;
273
    }
274

    
275
    private boolean isNotBlank(String str) {
276
        return StringUtils.isNotBlank(str);
277
    }
278

    
279
    private boolean isBlank(String str) {
280
        return StringUtils.isBlank(str);
281
    }
282
}
    (1-1/1)