a326f5ac852f1f5a6b1727838c27aeaeeb7ee721
[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
221
222
223 @Override
224 public String getFullTitleCache(T nonViralName) {
225 //null
226 if (nonViralName == null){
227 return null;
228 }
229 //full title cache
230 if (nonViralName.isProtectedFullTitleCache() == true) {
231 return nonViralName.getFullTitleCache();
232 }
233
234 String result = "";
235 //title cache
236 String titleCache = nonViralName.getTitleCache(); // OLD: getTitleCache(nonViralName);
237
238 String microReference = nonViralName.getNomenclaturalMicroReference();
239 INomenclaturalReference ref = nonViralName.getNomenclaturalReference();
240 String referenceBaseCache = null;
241 if (ref != null){
242 INomenclaturalReference nomenclaturalReference = HibernateProxyHelper.deproxy(ref, INomenclaturalReference.class);
243 nomenclaturalReference.setCacheStrategy(nomenclaturalReference.getType().getCacheStrategy());
244 referenceBaseCache = nomenclaturalReference.getNomenclaturalCitation(microReference);
245 }
246
247 //make nomenclatural status
248 String ncStatusCache = "";
249 Set<NomenclaturalStatus> ncStati = nonViralName.getStatus();
250 Iterator<NomenclaturalStatus> iterator = ncStati.iterator();
251 while (iterator.hasNext()) {
252 NomenclaturalStatus ncStatus = (NomenclaturalStatus)iterator.next();
253 // since the NewInstance method of nomencatural status allows null as parameter
254 // we have to check for null values here
255 String suffix = "not defined";
256 if(ncStatus.getType() != null){
257 NomenclaturalStatusType statusType = ncStatus.getType();
258 Language lang = Language.LATIN();
259 Representation repr = statusType.getRepresentation(lang);
260 if (repr != null){
261 suffix = repr.getAbbreviatedLabel();
262 }else{
263 String message = "No latin representation available for nom. status. " + statusType.getTitleCache();
264 logger.warn(message);
265 throw new IllegalStateException(message);
266 }
267 }else if(ncStatus.getRuleConsidered() != null && ! ncStatus.getRuleConsidered().equals("")){
268 suffix = ncStatus.getRuleConsidered();
269 }
270 ncStatusCache = ", " + suffix;
271 }
272 String refConcat = " ";
273 if (referenceBaseCache != null && ! referenceBaseCache.trim().startsWith("in ")){
274 refConcat = ", ";
275 }
276 result = CdmUtils.concat(refConcat, titleCache, referenceBaseCache);
277 result = CdmUtils.concat("", result, ncStatusCache);
278 return result;
279 }
280
281
282 /**
283 * Generates and returns the "name cache" (only scientific name without author teams and year).
284 * @see eu.etaxonomy.cdm.strategy.cache.name.INameCacheStrategy#getNameCache(eu.etaxonomy.cdm.model.name.TaxonNameBase)
285 */
286 public String getNameCache(T nonViralName) {
287 if (nonViralName == null){
288 return null;
289 }
290 String result;
291 Rank rank = nonViralName.getRank();
292
293 if (nonViralName.isProtectedNameCache()){
294 result = nonViralName.getNameCache();
295 }else if (rank == null){
296 result = getRanklessNameCache(nonViralName);
297 }else if (rank.isInfraSpecific()){
298 result = getInfraSpeciesNameCache(nonViralName);
299 }else if (rank.isSpecies()){
300 result = getSpeciesNameCache(nonViralName);
301 }else if (rank.isInfraGeneric()){
302 result = getInfraGenusNameCache(nonViralName);
303 }else if (rank.isGenus()){
304 result = getGenusOrUninomialNameCache(nonViralName);
305 }else if (rank.isSupraGeneric()){
306 result = getGenusOrUninomialNameCache(nonViralName);
307 }else{
308 logger.warn("Name Strategy for Name (UUID: " + nonViralName.getUuid() + ") not yet implemented");
309 result = "";
310 }
311 return result;
312 }
313
314
315 /* (non-Javadoc)
316 * @see eu.etaxonomy.cdm.strategy.cache.INonViralNameCacheStrategy#getAuthorCache(eu.etaxonomy.cdm.model.name.NonViralName)
317 */
318 public String getAuthorshipCache(T nonViralName) {
319 if (nonViralName == null){
320 return null;
321 }
322 //cache protected
323 if (nonViralName.isProtectedAuthorshipCache() == true) {
324 return nonViralName.getAuthorshipCache();
325 }
326 return getNonCacheAuthorshipCache(nonViralName);
327
328 }
329
330 /**
331 * Returns the authorshipcache string for the atomized authorship fields. Does not use the authorshipfield.
332 * @throws NullPointerException if nonViralName is null.
333 * @param nonViralName
334 * @return
335 */
336 protected String getNonCacheAuthorshipCache(T nonViralName){
337 String result = "";
338 INomenclaturalAuthor combinationAuthor = nonViralName.getCombinationAuthorTeam();
339 INomenclaturalAuthor exCombinationAuthor = nonViralName.getExCombinationAuthorTeam();
340 INomenclaturalAuthor basionymAuthor = nonViralName.getBasionymAuthorTeam();
341 INomenclaturalAuthor exBasionymAuthor = nonViralName.getExBasionymAuthorTeam();
342 String basionymPart = "";
343 String authorPart = "";
344 //basionym
345 if (basionymAuthor != null || exBasionymAuthor != null){
346 basionymPart = BasionymStart + getAuthorAndExAuthor(basionymAuthor, exBasionymAuthor) + BasionymEnd;
347 }
348 if (combinationAuthor != null || exCombinationAuthor != null){
349 authorPart = getAuthorAndExAuthor(combinationAuthor, exCombinationAuthor);
350 }
351 result = CdmUtils.concat(BasionymAuthorCombinationAuthorSeperator, basionymPart, authorPart);
352 return result;
353 }
354
355 /**
356 * Returns the AuthorCache part for a combination of an author and an ex author. This applies on combination authors
357 * as well as on basionym/orginal combination authors.
358 * @param author the author
359 * @param exAuthor the ex-author
360 * @return
361 */
362 protected String getAuthorAndExAuthor(INomenclaturalAuthor author, INomenclaturalAuthor exAuthor){
363 String result = "";
364 String authorString = "";
365 String exAuthorString = "";
366 if (author != null){
367 authorString = CdmUtils.Nz(author.getNomenclaturalTitle());
368 }
369 if (exAuthor != null){
370 exAuthorString = CdmUtils.Nz(exAuthor.getNomenclaturalTitle());
371 }
372 if (exAuthorString.length() > 0 ){
373 exAuthorString = exAuthorString + ExAuthorSeperator;
374 }
375 result = exAuthorString + authorString;
376 return result;
377
378 }
379
380
381 /* (non-Javadoc)
382 * @see eu.etaxonomy.cdm.strategy.INameCacheStrategy#getTaggedName(eu.etaxonomy.cdm.model.common.CdmBase)
383 */
384 @Override
385 public List<Object> getTaggedName(T nonViralName) {
386 List<Object> tags = new ArrayList<Object>();
387 if (nonViralName.getGenusOrUninomial() == null){
388 tags.add(nonViralName.getNameCache());
389 }else{
390 tags.add(nonViralName.getGenusOrUninomial());
391 }
392 if (nonViralName.isSpecies() || nonViralName.isInfraSpecific()){
393 tags.add(nonViralName.getSpecificEpithet());
394 }
395
396 // No autonym
397 if (nonViralName.isInfraSpecific() && ! nonViralName.getSpecificEpithet().equals(nonViralName.getInfraSpecificEpithet())){
398 tags.add(nonViralName.getRank());
399 tags.add(nonViralName.getInfraSpecificEpithet());
400 }
401
402 if (nonViralName.isInfraGeneric()){
403 //TODO choose right strategy or generic approach?
404 // --- strategy 1 ---
405
406 if (nonViralName.getRank().isSpeciesAggregate()){
407 tags.add(getSpeciesAggregateEpithet(nonViralName));
408 }else{
409 tags.add(nonViralName.getRank());
410 tags.add(nonViralName.getInfraGenericEpithet());
411 }
412 // --- strategy 2 ---
413 // tags.add('('+nvn.getInfraGenericEpithet()+')');
414 }
415 Team authorTeam = Team.NewInstance();
416 authorTeam.setProtectedTitleCache(true);
417 authorTeam.setTitleCache(nonViralName.getAuthorshipCache(), true);
418 tags.add(authorTeam);
419
420 // Name is an autonym. Rank and infraspecific eitheton follow the author
421 if (nonViralName.isInfraSpecific() && nonViralName.getSpecificEpithet().equals(nonViralName.getInfraSpecificEpithet())){
422 tags.add(nonViralName.getRank());
423 tags.add(nonViralName.getInfraSpecificEpithet());
424 }
425
426 if(! "".equals(nonViralName.getAppendedPhrase())&& (nonViralName.getAppendedPhrase() != null)){
427 tags.add(nonViralName.getAppendedPhrase());
428 }
429
430 return tags;
431 }
432
433
434 //***************************** PRIVATES ***************************************/
435
436 protected String getRanklessNameCache(NonViralName nonViralName){
437 String result = "";
438 result = (result + (nonViralName.getGenusOrUninomial())).trim().replace("null", "");
439 result += " " + (CdmUtils.Nz(nonViralName.getSpecificEpithet())).trim();
440 result += " " + (CdmUtils.Nz(nonViralName.getInfraSpecificEpithet())).trim();
441 result = result.trim().replace("null", "");
442 //result += " (rankless)";
443 result = addAppendedPhrase(result, nonViralName);
444 return result;
445 }
446
447
448 protected String getGenusOrUninomialNameCache(NonViralName nonViralName){
449 String result;
450 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial());
451 result = addAppendedPhrase(result, nonViralName).trim();
452 return result;
453 }
454
455 protected String getInfraGenusNameCache(NonViralName nonViralName){
456 String result;
457 Rank rank = nonViralName.getRank();
458 if (rank.isSpeciesAggregate()){
459 return getSpeciesAggregateCache(nonViralName);
460 }
461 String infraGenericMarker = "'unhandled infrageneric rank'";
462 if (rank != null){
463 try {
464 infraGenericMarker = rank.getInfraGenericMarker();
465 } catch (UnknownCdmTypeException e) {
466 infraGenericMarker = "'unhandled infrageneric rank'";
467 }
468 }
469 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial());
470 result += " " + infraGenericMarker + " " + (CdmUtils.Nz(nonViralName.getInfraGenericEpithet())).trim().replace("null", "");
471 result = addAppendedPhrase(result, nonViralName).trim();
472 return result;
473 }
474
475 // aggr.|agg.|group
476 protected String getSpeciesAggregateCache(NonViralName nonViralName){
477 String result;
478 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial());
479
480 result += " "+getSpeciesAggregateEpithet(nonViralName);
481 /*result += " " + CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim().replace("null", "");
482 String marker;
483 try {
484 marker = nonViralName.getRank().getInfraGenericMarker();
485 } catch (UnknownCdmTypeException e) {
486 marker = "'unknown aggregat type'";
487 }
488 result += " " + marker;*/
489 result = addAppendedPhrase(result, nonViralName).trim();
490 return result;
491 }
492
493 private String getSpeciesAggregateEpithet(NonViralName nonViralName) {
494 String result;
495
496 result = CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim().replace("null", "");
497 String marker;
498 try {
499 marker = nonViralName.getRank().getInfraGenericMarker();
500 } catch (UnknownCdmTypeException e) {
501 marker = "'unknown aggregat type'";
502 }
503 result += " " + marker;
504
505 return result;
506 }
507
508 protected String getSpeciesNameCache(NonViralName nonViralName){
509 String result;
510 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial());
511 result += " " + CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim().replace("null", "");
512 result = addAppendedPhrase(result, nonViralName).trim();
513 result = result.replace("\\s\\", " ");
514 return result;
515 }
516
517
518 protected String getInfraSpeciesNameCache(NonViralName nonViralName){
519 return getInfraSpeciesNameCache(nonViralName, true);
520 }
521
522 protected String getInfraSpeciesNameCache(NonViralName nonViralName, boolean includeMarker){
523 String result;
524 result = CdmUtils.Nz(nonViralName.getGenusOrUninomial());
525 result += " " + (CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim()).replace("null", "");
526 if (includeMarker){
527 result += " " + (nonViralName.getRank().getAbbreviation()).trim().replace("null", "");
528 }
529 result += " " + (CdmUtils.Nz(nonViralName.getInfraSpecificEpithet())).trim().replace("null", "");
530 result = addAppendedPhrase(result, nonViralName).trim();
531 return result;
532 }
533
534
535
536 /**
537 * @param name
538 * @return true, if name has Rank, Rank is below species and species epithet equals infraSpeciesEpithtet, else false
539 */
540 protected boolean isAutonym(NonViralName nonViralName){
541 if (nonViralName != null && nonViralName.getRank() != null && nonViralName.getSpecificEpithet() != null && nonViralName.getInfraSpecificEpithet() != null &&
542 nonViralName.getRank().isInfraSpecific() && nonViralName.getSpecificEpithet().trim().equals(nonViralName.getInfraSpecificEpithet().trim())){
543 return true;
544 }else{
545 return false;
546 }
547 }
548
549 protected String addAppendedPhrase(String resultString, NonViralName nonViralName){
550 String appendedPhrase = nonViralName ==null ? null : nonViralName.getAppendedPhrase();
551 if (resultString == null){
552 return appendedPhrase;
553 }else if(appendedPhrase == null || "".equals(appendedPhrase.trim())) {
554 return resultString;
555 }else if ("".equals(resultString)){
556 return resultString + appendedPhrase;
557 }else {
558 return resultString + " " + appendedPhrase;
559 }
560 }
561
562
563 public String getLastEpithet(T taxonNameBase) {
564 Rank rank = taxonNameBase.getRank();
565 if(rank.isGenus() || rank.isSupraGeneric()) {
566 return taxonNameBase.getGenusOrUninomial();
567 } else if(rank.isInfraGeneric()) {
568 return taxonNameBase.getInfraGenericEpithet();
569 } else if(rank.isSpecies()) {
570 return taxonNameBase.getSpecificEpithet();
571 } else {
572 return taxonNameBase.getInfraSpecificEpithet();
573 }
574 }
575 }