bugfix for namecachestrategy
[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 String result = "";
167 //Autonym
168 if (isAutonym(nonViralName)){
169 String speciesPart = getSpeciesNameCache(nonViralName);
170 //TODO should this include basionym authors and ex authors
171 INomenclaturalAuthor author = nonViralName.getCombinationAuthorTeam();
172 String authorPart = "";
173 if (author != null){
174 authorPart = CdmUtils.Nz(author.getNomenclaturalTitle());
175 }
176 INomenclaturalAuthor basAuthor = nonViralName.getBasionymAuthorTeam();
177 String basAuthorPart = "";
178 if (basAuthor != null){
179 basAuthorPart = CdmUtils.Nz(basAuthor.getNomenclaturalTitle());
180 }
181 if (! "".equals(basAuthorPart)){
182 authorPart = "("+ basAuthorPart +")" + authorPart;
183 }
184 String infraSpeciesPart = (CdmUtils.Nz(nonViralName.getInfraSpecificEpithet()));
185
186 String infraSpeciesSeparator = "";
187 if (nonViralName.getRank() == null || !nonViralName.getRank().isInfraSpecific()){
188 //TODO handle exception
189 logger.warn("Rank for autonym does not exist or is not lower than species !!");
190 }else{
191 infraSpeciesSeparator = nonViralName.getRank().getAbbreviation();
192 }
193
194 result = CdmUtils.concat(" ", new String[]{speciesPart, authorPart, infraSpeciesSeparator, infraSpeciesPart});
195 result = result.trim().replace("null", "");
196 }else{ //not Autonym
197 String nameCache = CdmUtils.Nz(getNameCache(nonViralName));
198 if (nameIncludesAuthorship(nonViralName)){
199 String authorCache = CdmUtils.Nz(getAuthorshipCache(nonViralName));
200 result = CdmUtils.concat(NameAuthorSeperator, nameCache, authorCache);
201 }else{
202 result = nameCache;
203 }
204 }
205 return result;
206 }
207
208 protected boolean nameIncludesAuthorship(NonViralName nonViralName){
209 Rank rank = nonViralName.getRank();
210 if (rank != null && rank.isSpeciesAggregate()){
211 return false;
212 }else{
213 return true;
214 }
215 }
216
217
218 @Override
219 public String getFullTitleCache(T nonViralName) {
220 //null
221 if (nonViralName == null){
222 return null;
223 }
224 //full title cache
225 if (nonViralName.isProtectedFullTitleCache() == true) {
226 return nonViralName.getFullTitleCache();
227 }
228
229 String result = "";
230 //title cache
231 String titleCache = getTitleCache(nonViralName);
232
233 String microReference = nonViralName.getNomenclaturalMicroReference();
234 ReferenceBase<?> ref = nonViralName.getNomenclaturalReference();
235 String referenceBaseCache = null;
236 if (ref != null){
237 INomenclaturalReference nomRef = HibernateProxyHelper.deproxy(ref, INomenclaturalReference.class);
238 referenceBaseCache = nomRef.getNomenclaturalCitation(microReference);
239 }
240
241 //make nomenclatural status
242 String ncStatusCache = "";
243 Set<NomenclaturalStatus> ncStati = nonViralName.getStatus();
244 Iterator<NomenclaturalStatus> iterator = ncStati.iterator();
245 while (iterator.hasNext()) {
246 NomenclaturalStatus ncStatus = (NomenclaturalStatus)iterator.next();
247 NomenclaturalStatusType statusType = ncStatus.getType();
248 Language lang = Language.LATIN();
249 Representation repr = statusType.getRepresentation(lang);
250 ncStatusCache = ", " + repr.getAbbreviatedLabel();
251 }
252 String refConcat = " ";
253 if (referenceBaseCache != null && ! referenceBaseCache.trim().startsWith("in ")){
254 refConcat = ", ";
255 }
256 result = CdmUtils.concat(refConcat, titleCache, referenceBaseCache);
257 result = CdmUtils.concat("", result, ncStatusCache);
258 return result;
259 }
260
261
262 /**
263 * Generates and returns the "name cache" (only scientific name without author teams and year).
264 * @see eu.etaxonomy.cdm.strategy.cache.name.INameCacheStrategy#getNameCache(eu.etaxonomy.cdm.model.name.TaxonNameBase)
265 */
266 public String getNameCache(T nonViralName) {
267 if (nonViralName == null){
268 return null;
269 }
270 String result;
271 Rank rank = nonViralName.getRank();
272
273 if (nonViralName.isProtectedNameCache()){
274 result = nonViralName.getNameCache();
275 }else if (rank == null){
276 result = getRanklessNameCache(nonViralName);
277 }else if (rank.isInfraSpecific()){
278 result = getInfraSpeciesNameCache(nonViralName);
279 }else if (rank.isSpecies()){
280 result = getSpeciesNameCache(nonViralName);
281 }else if (rank.isInfraGeneric()){
282 result = getInfraGenusNameCache(nonViralName);
283 }else if (rank.isGenus()){
284 result = getGenusOrUninomialNameCache(nonViralName);
285 }else if (rank.isSupraGeneric()){
286 result = getGenusOrUninomialNameCache(nonViralName);
287 }else{
288 logger.warn("Name Strategy for Name (UUID: " + nonViralName.getUuid() + ") not yet implemented");
289 result = "";
290 }
291 return result;
292 }
293
294
295 /* (non-Javadoc)
296 * @see eu.etaxonomy.cdm.strategy.cache.INonViralNameCacheStrategy#getAuthorCache(eu.etaxonomy.cdm.model.name.NonViralName)
297 */
298 public String getAuthorshipCache(T nonViralName) {
299 if (nonViralName == null){
300 return null;
301 }
302 //cache protected
303 if (nonViralName.isProtectedAuthorshipCache() == true) {
304 return nonViralName.getAuthorshipCache();
305 }
306 return getNonCacheAuthorshipCache(nonViralName);
307
308 }
309
310 /**
311 * Returns the authorshipcache string for the atomized authorship fields. Does not use the authorshipfield.
312 * @throws NullPointerException if nonViralName is null.
313 * @param nonViralName
314 * @return
315 */
316 protected String getNonCacheAuthorshipCache(T nonViralName){
317 String result = "";
318 INomenclaturalAuthor combinationAuthor = nonViralName.getCombinationAuthorTeam();
319 INomenclaturalAuthor exCombinationAuthor = nonViralName.getExCombinationAuthorTeam();
320 INomenclaturalAuthor basionymAuthor = nonViralName.getBasionymAuthorTeam();
321 INomenclaturalAuthor exBasionymAuthor = nonViralName.getExBasionymAuthorTeam();
322 String basionymPart = "";
323 String authorPart = "";
324 //basionym
325 if (basionymAuthor != null || exBasionymAuthor != null){
326 basionymPart = BasionymStart + getAuthorAndExAuthor(basionymAuthor, exBasionymAuthor) + BasionymEnd;
327 }
328 if (combinationAuthor != null || exCombinationAuthor != null){
329 authorPart = getAuthorAndExAuthor(combinationAuthor, exCombinationAuthor);
330 }
331 result = CdmUtils.concat(BasionymAuthorCombinationAuthorSeperator, basionymPart, authorPart);
332 return result;
333 }
334
335 /**
336 * Returns the AuthorCache part for a combination of an author and an ex author. This applies on combination authors
337 * as well as on basionym/orginal combination authors.
338 * @param author the author
339 * @param exAuthor the ex-author
340 * @return
341 */
342 protected String getAuthorAndExAuthor(INomenclaturalAuthor author, INomenclaturalAuthor exAuthor){
343 String result = "";
344 String authorString = "";
345 String exAuthorString = "";
346 if (author != null){
347 authorString = CdmUtils.Nz(author.getNomenclaturalTitle());
348 }
349 if (exAuthor != null){
350 exAuthorString = CdmUtils.Nz(exAuthor.getNomenclaturalTitle());
351 }
352 if (exAuthorString.length() > 0 ){
353 exAuthorString = exAuthorString + ExAuthorSeperator;
354 }
355 result = exAuthorString + authorString;
356 return result;
357
358 }
359
360
361 /* (non-Javadoc)
362 * @see eu.etaxonomy.cdm.strategy.INameCacheStrategy#getTaggedName(eu.etaxonomy.cdm.model.common.CdmBase)
363 */
364 @Override
365 public List<Object> getTaggedName(T nonViralName) {
366 List<Object> tags = new ArrayList<Object>();
367 tags.add(nonViralName.getGenusOrUninomial());
368 if (nonViralName.isSpecies() || nonViralName.isInfraSpecific()){
369 tags.add(nonViralName.getSpecificEpithet());
370 }
371
372 // No autonym
373 if (nonViralName.isInfraSpecific() && ! nonViralName.getSpecificEpithet().equals(nonViralName.getInfraSpecificEpithet())){
374 tags.add(nonViralName.getRank());
375 tags.add(nonViralName.getInfraSpecificEpithet());
376 }
377
378 if (nonViralName.isInfraGeneric()){
379 //TODO choose right strategy or generic approach?
380 // --- strategy 1 ---
381 tags.add(nonViralName.getRank());
382 tags.add(nonViralName.getInfraGenericEpithet());
383 // --- strategy 2 ---
384 // tags.add('('+nvn.getInfraGenericEpithet()+')');
385 }
386 Team authorTeam = Team.NewInstance();
387 authorTeam.setProtectedTitleCache(true);
388 authorTeam.setTitleCache(nonViralName.getAuthorshipCache());
389 tags.add(authorTeam);
390
391 // Name is an autonym. Rank and infraspecific eitheton follow the author
392 if (nonViralName.isInfraSpecific() && nonViralName.getSpecificEpithet().equals(nonViralName.getInfraSpecificEpithet())){
393 tags.add(nonViralName.getRank());
394 tags.add(nonViralName.getInfraSpecificEpithet());
395 }
396
397 if(! "".equals(nonViralName.getAppendedPhrase())){
398 tags.add(nonViralName.getAppendedPhrase());
399 }
400
401 return tags;
402 }
403
404
405 /************** PRIVATES ****************/
406
407 protected String getRanklessNameCache(NonViralName nonViralName){
408 String result = "";
409 result = (result + (nonViralName.getGenusOrUninomial())).trim().replace("null", "");
410 result += " " + (CdmUtils.Nz(nonViralName.getSpecificEpithet())).trim();
411 result += " " + (CdmUtils.Nz(nonViralName.getInfraSpecificEpithet())).trim();
412 result = result.trim().replace("null", "");
413 //result += " (rankless)";
414 result = addAppendedPhrase(result, nonViralName);
415 return result;
416 }
417
418
419 protected String getGenusOrUninomialNameCache(NonViralName nonViralName){
420 String result;
421 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial());
422 result = addAppendedPhrase(result, nonViralName);
423 return result;
424 }
425
426 protected String getInfraGenusNameCache(NonViralName nonViralName){
427 String result;
428 Rank rank = nonViralName.getRank();
429 if (rank.isSpeciesAggregate()){
430 return getSpeciesAggregateCache(nonViralName);
431 }
432 String infraGenericMarker = "xxx.";
433 if (rank != null){
434 try {
435 infraGenericMarker = rank.getInfraGenericMarker();
436 } catch (UnknownCdmTypeException e) {
437 infraGenericMarker = "'unhandled infrageneric rank'";
438 }
439 }
440 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial());
441 result += " " + infraGenericMarker + " " + (CdmUtils.Nz(nonViralName.getInfraGenericEpithet())).trim().replace("null", "");
442 result = addAppendedPhrase(result, nonViralName);
443 return result;
444 }
445
446 // aggr.|agg.|group
447 protected String getSpeciesAggregateCache(NonViralName nonViralName){
448 String result;
449 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial());
450 result += " " + CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim().replace("null", "");
451 String marker;
452 try {
453 marker = nonViralName.getRank().getInfraGenericMarker();
454 } catch (UnknownCdmTypeException e) {
455 marker = "'unknown aggregat type'";
456 }
457 result += " " + marker;
458 result = addAppendedPhrase(result, nonViralName);
459 return result;
460 }
461
462 protected String getSpeciesNameCache(NonViralName nonViralName){
463 String result;
464 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial());
465 result += " " + CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim().replace("null", "");
466 result = addAppendedPhrase(result, nonViralName);
467 return result;
468 }
469
470
471 protected String getInfraSpeciesNameCache(NonViralName nonViralName){
472 String result;
473 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial());
474 result += " " + (CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim()).replace("null", "");
475 if (! isAutonym(nonViralName)){
476 result += " " + (nonViralName.getRank().getAbbreviation()).trim().replace("null", "");
477 }
478 result += " " + (CdmUtils.Nz(nonViralName.getInfraSpecificEpithet())).trim().replace("null", "");
479 result = addAppendedPhrase(result, nonViralName);
480 return result;
481 }
482
483
484 /**
485 * @param name
486 * @return true, if name has Rank, Rank is below species and species epithet equals infraSpeciesEpithtet, else false
487 */
488 protected boolean isAutonym(NonViralName nonViralName){
489 if (nonViralName != null && nonViralName.getRank() != null && nonViralName.getSpecificEpithet() != null && nonViralName.getInfraSpecificEpithet() != null &&
490 nonViralName.getRank().isInfraSpecific() && nonViralName.getSpecificEpithet().trim().equals(nonViralName.getInfraSpecificEpithet().trim())){
491 return true;
492 }else{
493 return false;
494 }
495 }
496
497 protected String addAppendedPhrase(String resultString, NonViralName nonViralName){
498 String appendedPhrase = nonViralName ==null ? null : nonViralName.getAppendedPhrase();
499 if (resultString == null){
500 return appendedPhrase;
501 }else if(appendedPhrase == null || "".equals(appendedPhrase.trim())) {
502 return resultString;
503 }else if ("".equals(resultString)){
504 return resultString + appendedPhrase;
505 }else {
506 return resultString + " " + appendedPhrase;
507 }
508 }
509
510
511 public String getLastEpithet(T taxonNameBase) {
512 Rank rank = taxonNameBase.getRank();
513 if(rank.isGenus() || rank.isSupraGeneric()) {
514 return taxonNameBase.getGenusOrUninomial();
515 } else if(rank.isInfraGeneric()) {
516 return taxonNameBase.getInfraGenericEpithet();
517 } else if(rank.isSpecies()) {
518 return taxonNameBase.getSpecificEpithet();
519 } else {
520 return taxonNameBase.getInfraSpecificEpithet();
521 }
522 }
523 }