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