ref #10161 defined order for multiple nom. status
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / strategy / cache / name / NameCacheStrategyBase.java
1 /**
2 * Copyright (C) 2007 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.name;
10
11 import java.util.ArrayList;
12 import java.util.Arrays;
13 import java.util.Collection;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.UUID;
17
18 import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;
19
20 import eu.etaxonomy.cdm.common.CdmUtils;
21 import eu.etaxonomy.cdm.compare.name.NomenclaturalStatusComparator;
22 import eu.etaxonomy.cdm.format.reference.NomenclaturalSourceFormatter;
23 import eu.etaxonomy.cdm.model.common.CdmBase;
24 import eu.etaxonomy.cdm.model.common.Language;
25 import eu.etaxonomy.cdm.model.name.INonViralName;
26 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
27 import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
28 import eu.etaxonomy.cdm.model.name.TaxonName;
29 import eu.etaxonomy.cdm.model.term.Representation;
30 import eu.etaxonomy.cdm.ref.TypedEntityReference;
31 import eu.etaxonomy.cdm.strategy.StrategyBase;
32 import eu.etaxonomy.cdm.strategy.cache.HTMLTagRules;
33 import eu.etaxonomy.cdm.strategy.cache.TagEnum;
34 import eu.etaxonomy.cdm.strategy.cache.TaggedCacheHelper;
35 import eu.etaxonomy.cdm.strategy.cache.TaggedText;
36 import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImplRegExBase;
37
38 /**
39 * @author AM
40 */
41 public abstract class NameCacheStrategyBase
42 extends StrategyBase
43 implements INameCacheStrategy {
44 private static final long serialVersionUID = -2322348388258675517L;
45
46 private static final Logger logger = LogManager.getLogger(NameCacheStrategyBase.class);
47
48 final static UUID uuid = UUID.fromString("817ae5b5-3ac2-414b-a134-a9ae86cba040");
49
50 public NameCacheStrategyBase() {
51 super();
52 }
53
54 @Override
55 public String getFullTitleCache(TaxonName taxonName, HTMLTagRules htmlTagRules) {
56 List<TaggedText> tags = getTaggedFullTitle(taxonName);
57 if (tags == null){
58 return null;
59 }else{
60 String result = createString(tags, htmlTagRules);
61 return result;
62 }
63 }
64
65 @Override
66 public String getFullTitleCache(TaxonName taxonName) {
67 return getFullTitleCache(taxonName, null);
68 }
69
70 @Override
71 public List<TaggedText> getNomStatusTags(TaxonName taxonName, boolean includeSeparatorBefore,
72 boolean includeSeparatorAfter) {
73
74
75 Collection<NomenclaturalStatus> ncStati = taxonName.getStatus();
76 if (ncStati.size() > 1) {
77 //order to have defined behavior
78 ncStati = new ArrayList<>(ncStati);
79 ((List<NomenclaturalStatus>)ncStati).sort(NomenclaturalStatusComparator.SINGLETON());
80 }
81 Iterator<NomenclaturalStatus> iterator = ncStati.iterator();
82 List<TaggedText> nomStatusTags = new ArrayList<>();
83 while (iterator.hasNext()) {
84 NomenclaturalStatus ncStatus = iterator.next();
85 // since the NewInstance method of nomencatural status allows null as parameter
86 // we have to check for null values here
87 String nomStatusStr = "not defined";
88 if(ncStatus.getType() != null){
89 NomenclaturalStatusType statusType = ncStatus.getType();
90 List<Language> prefLangs = Arrays.asList(new Language[]{Language.LATIN(), Language.DEFAULT()});
91 Representation repr = statusType.getPreferredRepresentation(prefLangs);
92 if (repr != null){
93 if(!Language.LATIN().equals(repr.getLanguage())){
94 String message = "No latin representation available for nom. status. " + statusType.getTitleCache();
95 logger.info(message);
96 }
97 nomStatusStr = repr.getAbbreviatedLabel();
98 }else{
99 String message = "No representation available for nom. status. " + statusType.getTitleCache();
100 logger.warn(message);
101 nomStatusStr = statusType.getTitleCache();
102 }
103 }else if(isNotBlank(ncStatus.getRuleConsidered())){
104 nomStatusStr = ncStatus.getRuleConsidered();
105 }
106 String statusSeparator = ", ";
107 if (includeSeparatorBefore){
108 nomStatusTags.add(new TaggedText(TagEnum.separator, statusSeparator));
109 }
110 nomStatusTags.add(new TaggedText(TagEnum.nomStatus, nomStatusStr, new TypedEntityReference<>(ncStatus.getClass(), ncStatus.getUuid())));
111 if (includeSeparatorAfter){
112 nomStatusTags.add(new TaggedText(TagEnum.postSeparator, ","));
113 }
114 }
115 return nomStatusTags;
116 }
117
118 @Override
119 public String getNameCache(TaxonName nonViralName) {
120 List<TaggedText> tags = getTaggedName(nonViralName);
121 if (tags == null){
122 return null;
123 }else{
124 String result = createString(tags);
125 return result;
126 }
127 }
128
129 @Override
130 public String getNameCache(TaxonName nonViralName, HTMLTagRules htmlTagRules) {
131 List<TaggedText> tags = getTaggedName(nonViralName);
132 if (tags == null){
133 return null;
134 }else{
135 String result = createString(tags, htmlTagRules);
136 return result;
137 }
138 }
139
140 /**
141 * Generates and returns the title cache of the given name.
142 * The title cache in general includes the name and the authorship and year for some types of names.
143 *
144 * @see eu.etaxonomy.cdm.strategy.INameCacheStrategy#getTitleCache(eu.etaxonomy.cdm.model.common.CdmBase)
145 * @see eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy#getTitleCache(eu.etaxonomy.cdm.model.common.IdentifiableEntity)
146 */
147 @Override
148 public String getTitleCache(TaxonName taxonName) {
149 return getTitleCache(taxonName, null);
150 }
151
152 @Override
153 public String getTitleCache(TaxonName taxonName, HTMLTagRules htmlTagRules) {
154 List<TaggedText> tags = getTaggedTitle(taxonName);
155 if (tags == null){
156 return null;
157 }else{
158 String result = createString(tags, htmlTagRules);
159 return result;
160 }
161 }
162
163 @Override
164 public List<TaggedText> getTaggedTitle(TaxonName taxonName) {
165 if (taxonName == null){
166 return null;
167 }
168 //TODO how to handle protected fullTitleCache here?
169
170 if (taxonName.isProtectedTitleCache()){
171 //protected title cache
172 List<TaggedText> tags = new ArrayList<>();
173 tags.add(new TaggedText(TagEnum.name, taxonName.getTitleCache()));
174 return tags;
175 }else{
176 return doGetTaggedTitle(taxonName);
177 }
178 }
179
180 protected abstract List<TaggedText> doGetTaggedTitle(TaxonName taxonName);
181
182 @Override
183 public List<TaggedText> getTaggedFullTitle(TaxonName taxonName) {
184 List<TaggedText> tags = new ArrayList<>();
185
186 //null
187 if (taxonName == null){
188 return null;
189 }
190
191 //protected full title cache
192 if (taxonName.isProtectedFullTitleCache()){
193 tags.add(new TaggedText(TagEnum.fullName, taxonName.getFullTitleCache()));
194 return tags;
195 }
196
197 //title cache
198 // String titleCache = nonViralName.getTitleCache();
199 List<TaggedText> titleTags = getTaggedTitle(taxonName);
200 tags.addAll(titleTags);
201
202 //reference
203 String referenceCache = NomenclaturalSourceFormatter.INSTANCE().format(taxonName.getNomenclaturalSource());
204 //add to tags
205 if (isNotBlank(referenceCache)){
206 if (! referenceCache.trim().startsWith("in ")){
207 String refConcat = ", ";
208 tags.add(new TaggedText(TagEnum.separator, refConcat));
209 }
210 tags.add(new TaggedText(TagEnum.reference, referenceCache));
211 }
212
213 addOriginalSpelling(tags, taxonName);
214
215 //nomenclatural status
216 tags.addAll(getNomStatusTags(taxonName, true, false));
217 return tags;
218 }
219
220 protected void addOriginalSpelling(List<TaggedText> tags, TaxonName currentName){
221
222 currentName = CdmBase.deproxy(currentName);
223 //Hibernate.initialize(currentName.getRelationsToThisName());
224 TaxonName originalName = currentName.getOriginalSpelling();
225 if (originalName != null){
226 String originalInfo;
227 tags.add(TaggedText.NewSeparatorInstance(" [as \""));
228 if (!originalName.isNonViral()){
229 originalInfo = originalName.getTitleCache();
230 tags.add(new TaggedText(TagEnum.name, originalInfo));
231 }else{
232 INonViralName originalNvName = CdmBase.deproxy(originalName);
233 originalInfo = makeOriginalInfo(originalNvName, tags);
234 for (String split : originalInfo.split(" ")){
235 if (split.matches(NonViralNameParserImplRegExBase.infraSpeciesMarker)
236 || split.matches(NonViralNameParserImplRegExBase.oldInfraSpeciesMarker)) {
237 tags.add(new TaggedText(TagEnum.rank, split));
238 }else{
239 tags.add(new TaggedText(TagEnum.name, split));
240 }
241 }
242 }
243 tags.add(TaggedText.NewSeparatorInstance("\"]"));
244 }else{
245 return;
246 }
247 }
248
249 private String makeOriginalInfo(INonViralName originalName,
250 List<TaggedText> currentNameTags) {
251 //use cache if necessary
252 String cacheToUse = null;
253 if (originalName.isProtectedNameCache() && isNotBlank(originalName.getNameCache())){
254 cacheToUse = originalName.getNameCache();
255 }else if (originalName.isProtectedTitleCache() && isNotBlank(originalName.getTitleCache())){
256 cacheToUse = originalName.getTitleCache();
257 }else if (originalName.isProtectedFullTitleCache() && isNotBlank(originalName.getFullTitleCache())){
258 cacheToUse = originalName.getFullTitleCache();
259 }
260 if (cacheToUse != null){
261 return cacheToUse;
262 }
263 //use atomized data
264 //get originalNameParts array
265 String originalInfo = originalName.getNameCache();
266 if (originalInfo == null){
267 originalInfo = originalName.getTitleCache();
268 }
269 if (originalInfo == null){ //should not happen
270 originalInfo = originalName.getFullTitleCache();
271 }
272 String[] originalNameSplit = originalInfo.split("\\s+");
273
274 //get current name parts
275 String currentNameString = createString(currentNameTags);
276 String[] currentNameSplit = currentNameString.split("\\s+");
277
278 //compute string
279 String result = originalInfo;
280 Integer firstDiff = null;
281 Integer lastDiff = -1;
282 for (int i = 0; i < Math.min(originalNameSplit.length, currentNameSplit.length); i++){
283 if (!originalNameSplit[i].equals(currentNameSplit[i])){
284 lastDiff = i;
285 firstDiff = (firstDiff == null) ? i : firstDiff;
286 }
287 }
288 if (firstDiff != null){
289 result = CdmUtils.concat(" ", Arrays.asList(originalNameSplit).subList(firstDiff, lastDiff+1).toArray(new String[0]));
290 }
291
292 return result;
293 }
294
295 protected String createString(List<TaggedText> tags) {
296 return TaggedCacheHelper.createString(tags);
297 }
298
299 protected String createString(List<TaggedText> tags, HTMLTagRules htmlTagRules) {
300 return TaggedCacheHelper.createString(tags, htmlTagRules);
301 }
302 }