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