Bugfix for zoological name cache strategy
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / strategy / cache / name / NonViralNameDefaultCacheStrategy.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.Iterator;
13 import java.util.List;
14 import java.util.Set;
15 import java.util.UUID;
16
17 import org.apache.log4j.Logger;
18
19 import eu.etaxonomy.cdm.common.CdmUtils;
20 import eu.etaxonomy.cdm.model.agent.INomenclaturalAuthor;
21 import eu.etaxonomy.cdm.model.agent.Team;
22 import eu.etaxonomy.cdm.model.common.Language;
23 import eu.etaxonomy.cdm.model.common.Representation;
24 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
25 import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
26 import eu.etaxonomy.cdm.model.name.NonViralName;
27 import eu.etaxonomy.cdm.model.name.Rank;
28 import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
29
30
31 /**
32 * This class is a default implementation for the INonViralNameCacheStrategy<T extends NonViralName> interface.
33 * The method actually implements a cache strategy for botanical names so no method has to be overwritten by
34 * a subclass for botanic names.
35 * Where differing from this Default BotanicNameCacheStrategy other subclasses should overwrite the existing methods
36 * e.g. a CacheStrategy for zoological names should overwrite getAuthorAndExAuthor
37 * @author a.mueller
38 */
39 /**
40 * @author AM
41 *
42 * @param <T>
43 */
44 public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends NameCacheStrategyBase<T> implements INonViralNameCacheStrategy<T> {
45 private static final Logger logger = Logger.getLogger(NonViralNameDefaultCacheStrategy.class);
46
47 final static UUID uuid = UUID.fromString("1cdda0d1-d5bc-480f-bf08-40a510a2f223");
48
49 protected String NameAuthorSeperator = " ";
50 protected String BasionymStart = "(";
51 protected String BasionymEnd = ")";
52 protected String ExAuthorSeperator = " ex ";
53 protected CharSequence BasionymAuthorCombinationAuthorSeperator = " ";
54
55 @Override
56 public UUID getUuid(){
57 return uuid;
58 }
59
60
61 /**
62 * Factory method
63 * @return NonViralNameDefaultCacheStrategy A new instance of NonViralNameDefaultCacheStrategy
64 */
65 public static NonViralNameDefaultCacheStrategy NewInstance(){
66 return new NonViralNameDefaultCacheStrategy();
67 }
68
69 /**
70 * Constructor
71 */
72 protected NonViralNameDefaultCacheStrategy(){
73 super();
74 }
75
76 /* **************** GETTER / SETTER **************************************/
77
78 /**
79 * String that separates the NameCache part from the AuthorCache part
80 * @return
81 */
82 public String getNameAuthorSeperator() {
83 return NameAuthorSeperator;
84 }
85
86
87 public void setNameAuthorSeperator(String nameAuthorSeperator) {
88 NameAuthorSeperator = nameAuthorSeperator;
89 }
90
91
92 /**
93 * String the basionym author part starts with e.g. '('.
94 * This should correspond with the {@link NonViralNameDefaultCacheStrategy#getBasionymEnd() basionymEnd} attribute
95 * @return
96 */
97 public String getBasionymStart() {
98 return BasionymStart;
99 }
100
101
102 public void setBasionymStart(String basionymStart) {
103 BasionymStart = basionymStart;
104 }
105
106
107 /**
108 * String the basionym author part ends with e.g. ')'.
109 * This should correspond with the {@link NonViralNameDefaultCacheStrategy#getBasionymStart() basionymStart} attribute
110 * @return
111 */
112 public String getBasionymEnd() {
113 return BasionymEnd;
114 }
115
116
117 public void setBasionymEnd(String basionymEnd) {
118 BasionymEnd = basionymEnd;
119 }
120
121
122 /**
123 * String to seperate ex author from author.
124 * @return
125 */
126 public String getExAuthorSeperator() {
127 return ExAuthorSeperator;
128 }
129
130
131 public void setExAuthorSeperator(String exAuthorSeperator) {
132 ExAuthorSeperator = exAuthorSeperator;
133 }
134
135
136 /**
137 * String that seperates the basionym/original_combination author part from the combination author part
138 * @return
139 */
140 public CharSequence getBasionymAuthorCombinationAuthorSeperator() {
141 return BasionymAuthorCombinationAuthorSeperator;
142 }
143
144
145 public void setBasionymAuthorCombinationAuthorSeperator(
146 CharSequence basionymAuthorCombinationAuthorSeperator) {
147 BasionymAuthorCombinationAuthorSeperator = basionymAuthorCombinationAuthorSeperator;
148 }
149
150
151 //** *****************************************************************************************/
152
153
154 /* (non-Javadoc)
155 * @see eu.etaxonomy.cdm.strategy.INameCacheStrategy#getNameCache()
156 */
157 @Override
158 public String getTitleCache(T nonViralName) {
159 if (nonViralName == null){
160 return null;
161 }
162 String result = "";
163 if (isAutonym(nonViralName)){
164 String speciesPart = getSpeciesNameCache(nonViralName);
165 //TODO should this include basionym authors and ex authors
166 INomenclaturalAuthor author = nonViralName.getCombinationAuthorTeam();
167 String authorPart = "";
168 if (author != null){
169 authorPart = CdmUtils.Nz(author.getNomenclaturalTitle());
170 }
171 INomenclaturalAuthor basAuthor = nonViralName.getBasionymAuthorTeam();
172 String basAuthorPart = "";
173 if (basAuthor != null){
174 basAuthorPart = CdmUtils.Nz(basAuthor.getNomenclaturalTitle());
175 }
176 if (! "".equals(basAuthorPart)){
177 authorPart = "("+ basAuthorPart +")" + authorPart;
178 }
179 String infraSpeciesPart = (CdmUtils.Nz(nonViralName.getInfraSpecificEpithet()));
180
181 String infraSpeciesSeparator = "";
182 if (nonViralName.getRank() == null || !nonViralName.getRank().isInfraSpecific()){
183 //TODO handle exception
184 logger.warn("Rank for autonym does not exist or is not lower than species !!");
185 }else{
186 infraSpeciesSeparator = nonViralName.getRank().getAbbreviation();
187 }
188
189 result = CdmUtils.concat(" ", new String[]{speciesPart, authorPart, infraSpeciesSeparator, infraSpeciesPart});
190 result = result.trim().replace("null", "");
191 }else{ //not Autonym
192 String nameCache = CdmUtils.Nz(getNameCache(nonViralName));
193 String authorCache = CdmUtils.Nz(getAuthorshipCache(nonViralName));
194 result = CdmUtils.concat(NameAuthorSeperator, nameCache, authorCache);
195 }
196 return result;
197 }
198
199
200 @Override
201 public String getFullTitleCache(T nonViralName) {
202 //null
203 if (nonViralName == null){
204 return null;
205 }
206 //full title cache
207 if (nonViralName.isProtectedFullTitleCache() == true) {
208 return nonViralName.getFullTitleCache();
209 }
210
211 String result = "";
212 //title cache
213 String titleCache = getTitleCache(nonViralName);
214
215 String microReference = nonViralName.getNomenclaturalMicroReference();
216 INomenclaturalReference ref = (INomenclaturalReference)nonViralName.getNomenclaturalReference();
217 String referenceBaseCache = null;
218 if (ref != null){
219 referenceBaseCache = ref.getNomenclaturalCitation(microReference);
220 }
221
222 //make nomenclatural status
223 String ncStatusCache = "";
224 Set<NomenclaturalStatus> ncStati = nonViralName.getStatus();
225 Iterator<NomenclaturalStatus> iterator = ncStati.iterator();
226 while (iterator.hasNext()) {
227 NomenclaturalStatus ncStatus = (NomenclaturalStatus)iterator.next();
228 NomenclaturalStatusType statusType = ncStatus.getType();
229 Language lang = Language.LATIN();
230 Representation repr = statusType.getRepresentation(lang);
231 ncStatusCache = ", " + repr.getAbbreviatedLabel();
232 }
233 String refConcat = " ";
234 if (referenceBaseCache != null && ! referenceBaseCache.trim().startsWith("in ")){
235 refConcat = ", ";
236 }
237 result = CdmUtils.concat(refConcat, titleCache, referenceBaseCache);
238 result = CdmUtils.concat("", result, ncStatusCache);
239 return result;
240 }
241
242
243 /**
244 * Generates and returns the "name cache" (only scientific name without author teams and year).
245 * @see eu.etaxonomy.cdm.strategy.cache.name.INameCacheStrategy#getNameCache(eu.etaxonomy.cdm.model.name.TaxonNameBase)
246 */
247 public String getNameCache(T nonViralName) {
248 if (nonViralName == null){
249 return null;
250 }
251 String result;
252 Rank rank = nonViralName.getRank();
253
254 if (rank == null){
255 result = getRanklessNameCache(nonViralName);
256 }else if (rank.isInfraSpecific()){
257 result = getInfraSpeciesNameCache(nonViralName);
258 }else if (rank.isSpecies()){
259 result = getSpeciesNameCache(nonViralName);
260 }else if (rank.isInfraGeneric()){
261 result = getInfraGenusNameCache(nonViralName);
262 }else if (rank.isGenus()){
263 result = getGenusOrUninomialNameCache(nonViralName);
264 }else if (rank.isSupraGeneric()){
265 result = getGenusOrUninomialNameCache(nonViralName);
266 }else{
267 logger.warn("Name Strategy for Name (UUID: " + nonViralName.getUuid() + ") not yet implemented");
268 result = "";
269 }
270 return result;
271 }
272
273
274 /* (non-Javadoc)
275 * @see eu.etaxonomy.cdm.strategy.cache.INonViralNameCacheStrategy#getAuthorCache(eu.etaxonomy.cdm.model.name.NonViralName)
276 */
277 public String getAuthorshipCache(T nonViralName) {
278 if (nonViralName == null){
279 return null;
280 }
281 //cache protected
282 if (nonViralName.isProtectedAuthorshipCache() == true) {
283 return nonViralName.getAuthorshipCache();
284 }
285 return getNonCacheAuthorshipCache(nonViralName);
286
287 }
288
289 /**
290 * Returns the authorshipcache string for the atomized authorship fields. Does not use the authorshipfield.
291 * @throws NullPointerException if nonViralName is null.
292 * @param nonViralName
293 * @return
294 */
295 protected String getNonCacheAuthorshipCache(T nonViralName){
296 String result = "";
297 INomenclaturalAuthor combinationAuthor = nonViralName.getCombinationAuthorTeam();
298 INomenclaturalAuthor exCombinationAuthor = nonViralName.getExCombinationAuthorTeam();
299 INomenclaturalAuthor basionymAuthor = nonViralName.getBasionymAuthorTeam();
300 INomenclaturalAuthor exBasionymAuthor = nonViralName.getExBasionymAuthorTeam();
301 String basionymPart = "";
302 String authorPart = "";
303 //basionym
304 if (basionymAuthor != null || exBasionymAuthor != null){
305 basionymPart = BasionymStart + getAuthorAndExAuthor(basionymAuthor, exBasionymAuthor) + BasionymEnd;
306 }
307 if (combinationAuthor != null || exCombinationAuthor != null){
308 authorPart = getAuthorAndExAuthor(combinationAuthor, exCombinationAuthor);
309 }
310 result = CdmUtils.concat(BasionymAuthorCombinationAuthorSeperator, basionymPart, authorPart);
311 return result;
312 }
313
314 /**
315 * Returns the AuthorCache part for a combination of an author and an ex author. This applies on combination authors
316 * as well as on basionym/orginal combination authors.
317 * @param author the author
318 * @param exAuthor the ex-author
319 * @return
320 */
321 protected String getAuthorAndExAuthor(INomenclaturalAuthor author, INomenclaturalAuthor exAuthor){
322 String result = "";
323 String authorString = "";
324 String exAuthorString = "";
325 if (author != null){
326 authorString = CdmUtils.Nz(author.getNomenclaturalTitle());
327 }
328 if (exAuthor != null){
329 exAuthorString = CdmUtils.Nz(exAuthor.getNomenclaturalTitle());
330 }
331 if (exAuthorString.length() > 0 ){
332 exAuthorString = exAuthorString + ExAuthorSeperator;
333 }
334 result = exAuthorString + authorString;
335 return result;
336
337 }
338
339
340 /* (non-Javadoc)
341 * @see eu.etaxonomy.cdm.strategy.INameCacheStrategy#getTaggedName(eu.etaxonomy.cdm.model.common.CdmBase)
342 */
343 @Override
344 public List<Object> getTaggedName(T nonViralName) {
345 List<Object> tags = new ArrayList<Object>();
346 tags.add(nonViralName.getGenusOrUninomial());
347 if (nonViralName.isSpecies() || nonViralName.isInfraSpecific()){
348 tags.add(nonViralName.getSpecificEpithet());
349 }
350
351 // No autonym
352 if (nonViralName.isInfraSpecific() && ! nonViralName.getSpecificEpithet().equals(nonViralName.getInfraSpecificEpithet())){
353 tags.add(nonViralName.getRank());
354 tags.add(nonViralName.getInfraSpecificEpithet());
355 }
356
357 if (nonViralName.isInfraGeneric()){
358 //TODO choose right strategy or generic approach?
359 // --- strategy 1 ---
360 tags.add(nonViralName.getRank());
361 tags.add(nonViralName.getInfraGenericEpithet());
362 // --- strategy 2 ---
363 // tags.add('('+nvn.getInfraGenericEpithet()+')');
364 }
365 Team authorTeam = Team.NewInstance();
366 authorTeam.setProtectedTitleCache(true);
367 authorTeam.setTitleCache(nonViralName.getAuthorshipCache());
368 tags.add(authorTeam);
369
370 // Name is an autonym. Rank and infraspecific eitheton follow the author
371 if (nonViralName.isInfraSpecific() && nonViralName.getSpecificEpithet().equals(nonViralName.getInfraSpecificEpithet())){
372 tags.add(nonViralName.getRank());
373 tags.add(nonViralName.getInfraSpecificEpithet());
374 }
375
376 if(! "".equals(nonViralName.getAppendedPhrase())){
377 tags.add(nonViralName.getAppendedPhrase());
378 }
379
380 return tags;
381 }
382
383
384 /************** PRIVATES ****************/
385
386 protected String getRanklessNameCache(NonViralName nonViralName){
387 String result = "";
388 result = (result + (nonViralName.getGenusOrUninomial())).trim().replace("null", "");
389 result += " " + (CdmUtils.Nz(nonViralName.getSpecificEpithet())).trim();
390 result += " " + (CdmUtils.Nz(nonViralName.getInfraSpecificEpithet())).trim();
391 result = result.trim().replace("null", "");
392 //result += " (rankless)";
393 result = addAppendedPhrase(result, nonViralName);
394 return result;
395 }
396
397
398 protected String getGenusOrUninomialNameCache(NonViralName nonViralName){
399 String result;
400 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial());
401 result = addAppendedPhrase(result, nonViralName);
402 return result;
403 }
404
405 protected String getInfraGenusNameCache(NonViralName nonViralName){
406 String result;
407 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial());
408 result += " (" + (CdmUtils.Nz(nonViralName.getInfraGenericEpithet()) + ")").trim().replace("null", "");
409 result = addAppendedPhrase(result, nonViralName);
410 return result;
411 }
412
413
414 protected String getSpeciesNameCache(NonViralName nonViralName){
415 String result;
416 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial());
417 result += " " + CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim().replace("null", "");
418 result = addAppendedPhrase(result, nonViralName);
419 return result;
420 }
421
422
423 protected String getInfraSpeciesNameCache(NonViralName nonViralName){
424 String result;
425 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial());
426 result += " " + (CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim()).replace("null", "");
427 if (! isAutonym(nonViralName)){
428 result += " " + (nonViralName.getRank().getAbbreviation()).trim().replace("null", "");
429 }
430 result += " " + (CdmUtils.Nz(nonViralName.getInfraSpecificEpithet())).trim().replace("null", "");
431 result = addAppendedPhrase(result, nonViralName);
432 return result;
433 }
434
435
436 /**
437 * @param name
438 * @return true, if name has Rank, Rank is below species and species epithet equals infraSpeciesEpithtet, else false
439 */
440 protected boolean isAutonym(NonViralName nonViralName){
441 if (nonViralName != null && nonViralName.getRank() != null && nonViralName.getSpecificEpithet() != null && nonViralName.getInfraSpecificEpithet() != null &&
442 nonViralName.getRank().isInfraSpecific() && nonViralName.getSpecificEpithet().trim().equals(nonViralName.getInfraSpecificEpithet().trim())){
443 return true;
444 }else{
445 return false;
446 }
447 }
448
449 protected String addAppendedPhrase(String resultString, NonViralName nonViralName){
450 String appendedPhrase = nonViralName ==null ? null : nonViralName.getAppendedPhrase();
451 if (resultString == null){
452 return appendedPhrase;
453 }else if(appendedPhrase == null || "".equals(appendedPhrase.trim())) {
454 return resultString;
455 }else if ("".equals(resultString)){
456 return resultString + appendedPhrase;
457 }else {
458 return resultString + " " + appendedPhrase;
459 }
460 }
461
462
463 public String getLastEpithet(T taxonNameBase) {
464 Rank rank = taxonNameBase.getRank();
465 if(rank.isGenus() || rank.isSupraGeneric()) {
466 return taxonNameBase.getGenusOrUninomial();
467 } else if(rank.isInfraGeneric()) {
468 return taxonNameBase.getInfraGenericEpithet();
469 } else if(rank.isSpecies()) {
470 return taxonNameBase.getSpecificEpithet();
471 } else {
472 return taxonNameBase.getInfraSpecificEpithet();
473 }
474 }
475 }