remove whitespace after title for default references with only title and year
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / strategy / cache / reference / DefaultReferenceCacheStrategy.java
1 /**
2 * Copyright (C) 2016 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.reference;
10
11 import java.util.List;
12 import java.util.UUID;
13
14 import org.apache.commons.lang.StringUtils;
15 import org.apache.log4j.Logger;
16 import org.joda.time.DateTime;
17 import org.joda.time.format.DateTimeFormat;
18 import org.joda.time.format.DateTimeFormatter;
19
20 import eu.etaxonomy.cdm.common.CdmUtils;
21 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
22 import eu.etaxonomy.cdm.model.agent.Person;
23 import eu.etaxonomy.cdm.model.agent.Team;
24 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
25 import eu.etaxonomy.cdm.model.common.CdmBase;
26 import eu.etaxonomy.cdm.model.common.VerbatimTimePeriod;
27 import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
28 import eu.etaxonomy.cdm.model.reference.Reference;
29 import eu.etaxonomy.cdm.model.reference.ReferenceType;
30 import eu.etaxonomy.cdm.strategy.StrategyBase;
31
32 /**
33 * #5833
34 * The new single default cache strategy for {@link Reference references}.
35 * As we do have only one {@link Reference} class left which implements multiple interfaces,
36 * we may also only need 1 single cache strategy. However, care must be taken as the formatting
37 * differs dependent on the type an the in-reference structure.
38 *
39 * Generally the cache strategy computes allows 3 formattings:<BR>
40 *
41 * 1.) for bibliographic references (stored in {@link Reference#getTitleCache() titleCache}).<BR>
42 *
43 * 2.) for nomenclatural references (stored in {@link Reference#getAbbrevTitleCache() abbrevTitleCache}),
44 * but without micro reference (detail).<BR>
45 *
46 * 3.) for nomenclatural references with micro reference, but not stored anywhere as the micro reference
47 * is part of the name, not of the reference<BR>
48 *
49 * 4.) for short citation (e.g. Author 2009) as defined in {@link IReferenceCacheStrategy#getCitation(Reference)}
50 *
51 * @author a.mueller
52 * @since 25.05.2016
53 *
54 */
55 public class DefaultReferenceCacheStrategy extends StrategyBase implements INomenclaturalReferenceCacheStrategy{
56 private static final long serialVersionUID = 6773742298840407263L;
57
58 private static final Logger logger = Logger.getLogger(DefaultReferenceCacheStrategy.class);
59
60 private final static UUID uuid = UUID.fromString("63e669ca-c6be-4a8a-b157-e391c22580f9");
61
62 //article
63 public static final String UNDEFINED_JOURNAL = "- undefined journal -";
64 private static final String afterAuthor = ", ";
65
66 //book
67
68
69 //(book?) section
70 private String afterSectionAuthor = " - ";
71
72 //in reference
73 private String inSeparator = "in ";
74 private static final String afterInRefAuthor = ", ";
75
76 //common
77 private static final String blank = " ";
78 private static final String beforeYear = ". ";
79 private static final String beforeMicroReference = ": ";
80 private static final String afterYear = "";
81
82
83 private static final boolean trim = true;
84
85 // ************************ FACTORY ****************************/
86
87 /**
88 * Factory method
89 * @return
90 */
91 public static DefaultReferenceCacheStrategy NewInstance(){
92 return new DefaultReferenceCacheStrategy();
93 }
94
95
96 @Override
97 protected UUID getUuid() {
98 return uuid;
99 }
100
101 // ******************************* Main methods ******************************/
102
103 @Override
104 public String getTitleCache(Reference reference) {
105 if (reference == null){
106 return null;
107 }
108 if (reference.isProtectedTitleCache()){
109 return reference.getTitleCache();
110 }
111 boolean isNotAbbrev = false;
112
113 String result;
114 ReferenceType type = reference.getType();
115
116 if (isRealInRef(reference)){
117 result = titleCacheRealInRef(reference, isNotAbbrev);
118 }else if(isNomRef(type)){
119 //all Non-InRef NomRefs
120 result = getTitleWithoutYearAndAuthor(reference, isNotAbbrev);
121 result = addPages(result, reference);
122 result = addYear(result, reference, false);
123 TeamOrPersonBase<?> team = reference.getAuthorship();
124
125 if (type == ReferenceType.Article){
126 result = CdmUtils.concat(" ", reference.getTitle(), result);
127 if (team != null && isNotBlank(team.getTitleCache())){
128 String authorSeparator = isNotBlank(reference.getTitle())? afterAuthor : " ";
129 result = team.getTitleCache() + authorSeparator + result;
130 }
131 }else{ //if Book, CdDvd, flat Generic, Thesis, WebPage
132 if (team != null){
133 String teamTitle = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
134 team.getNomenclaturalTitle(), isNotAbbrev, trim);
135 if (teamTitle.length() > 0 ){
136 String concat = isNotBlank(result) ? afterAuthor : "";
137 result = teamTitle + concat + result;
138 }
139 }
140 }
141 }else if (type == ReferenceType.Journal){
142 result = titleCacheJournal(reference, isNotAbbrev);
143 }else{
144 result = titleCacheDefaultReference(reference, isNotAbbrev);
145 }
146 if (reference.getType() == ReferenceType.WebPage && reference.getUri() != null && !result.contains(reference.getUri().toString())){
147 //might become UTF8.EN_DASH in future
148 result = CdmUtils.concat(" - ", result, reference.getUri().toString());
149 }
150 if(reference.getAccessed() != null){
151 //TODO still a bit preliminary, also brackets may change in future
152 result = result + " [accessed " + getAccessedString(reference.getAccessed()) +"]";
153 }
154 return result;
155 }
156
157
158 /**
159 * @param accessed
160 * @return
161 */
162 private String getAccessedString(DateTime accessed) {
163 DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm");
164 String result = formatter.print(accessed);
165 if (result.endsWith(" 00:00")){
166 result = result.replace(" 00:00", "");
167 }
168 return result;
169 }
170
171 private String addPages(String result, Reference reference) {
172 //pages
173 if (isNotBlank(reference.getPages())){
174 //Removing trailing added just in case, maybe not necessary
175 result = RemoveTrailingDot(Nz(result)).trim() + ": " + reference.getPages();
176 }
177 return result;
178 }
179
180 private static String RemoveTrailingDot(String str) {
181 if (str != null && str.endsWith(".")){
182 str = str.substring(0, str.length()-1);
183 }
184 return str;
185 }
186
187
188 @Override
189 public String getFullAbbrevTitleString(Reference reference) {
190 if (reference == null){
191 return null;
192 }
193 String result;
194 ReferenceType type = reference.getType();
195 boolean isAbbrev = true;
196
197 if (reference.isProtectedAbbrevTitleCache()){
198 return reference.getAbbrevTitleCache();
199 }
200
201 if (type == ReferenceType.Article){
202 result = getTitleWithoutYearAndAuthor(reference, isAbbrev);
203 boolean useFullDatePublished = false;
204 result = addYear(result, reference, useFullDatePublished);
205 TeamOrPersonBase<?> team = reference.getAuthorship();
206 String articleTitle = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
207 reference.getAbbrevTitle(), isAbbrev, trim);
208 result = CdmUtils.concat(" ", articleTitle, result); //Article should maybe left out for nomenclatural references (?)
209 if (team != null && isNotBlank(team.getNomenclaturalTitle())){
210 String authorSeparator = isNotBlank(articleTitle) ? afterAuthor : " ";
211 result = team.getNomenclaturalTitle() + authorSeparator + result;
212 }
213 }else if (isRealInRef(reference)){
214 result = titleCacheRealInRef(reference, isAbbrev);
215 }else if (isNomRef(type)){
216 //FIXME same as titleCache => try to merge, but note article case
217 result = getTitleWithoutYearAndAuthor(reference, isAbbrev);
218 boolean useFullDatePublished = false;
219 result = addYear(result, reference, useFullDatePublished);
220 TeamOrPersonBase<?> team = reference.getAuthorship();
221
222 if (team != null){
223 String teamTitle = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
224 team.getNomenclaturalTitle(), isAbbrev, trim);
225 if (teamTitle.length() > 0 ){
226 String concat = isNotBlank(result) ? afterAuthor : "";
227 result = teamTitle + concat + result;
228 }
229 }
230 }else if(type == ReferenceType.Journal){
231 result = titleCacheJournal(reference, isAbbrev);
232 }else{
233 result = titleCacheDefaultReference(reference, isAbbrev);
234 }
235
236 return result;
237 }
238
239 @Override
240 public String getCitation(Reference reference) {
241 // mostly copied from nomRefCacheStrat, refCache, journalCache
242
243 if (reference == null){
244 return null;
245 }
246 StringBuilder stringBuilder = new StringBuilder();
247 TeamOrPersonBase<?> team = reference.getAuthorship();
248
249 String nextConcat = "";
250
251 if (team != null && isNotBlank(team.getTitleCache())){
252 stringBuilder.append(team.getTitleCache() );
253 //here is the difference between nomRef and others
254 if (isNomRef(reference.getType())) {
255 nextConcat = afterAuthor;
256 }else{
257 //FIXME check if this really makes sense
258 stringBuilder.append(afterAuthor);
259 nextConcat = beforeYear;
260 }
261 }
262
263 String year = reference.getYear();
264 if (StringUtils.isNotBlank(year)){
265 stringBuilder.append(nextConcat + year);
266 }
267
268 return stringBuilder.toString();
269 }
270
271 public String createShortCitation(Reference reference) {
272 TeamOrPersonBase<?> authorship = reference.getAuthorship();
273 String shortCitation = "";
274 if (authorship == null) {
275 return null;
276 }
277 authorship = HibernateProxyHelper.deproxy(authorship);
278 if (authorship instanceof Person){
279 shortCitation = ((Person)authorship).getFamilyName();
280 if (StringUtils.isBlank(shortCitation) ){
281 shortCitation = ((Person)authorship).getTitleCache();
282 }
283 }
284 else if (authorship instanceof Team){
285
286 Team authorTeam = HibernateProxyHelper.deproxy(authorship, Team.class);
287 int index = 0;
288
289 for (Person teamMember : authorTeam.getTeamMembers()){
290 index++;
291 if (index == 3){
292 shortCitation += " & al.";
293 break;
294 }
295 String concat = concatString(authorTeam, authorTeam.getTeamMembers(), index, ", ", " & ");
296 if (teamMember.getFamilyName() != null){
297 shortCitation += concat + teamMember.getFamilyName();
298 }else{
299 shortCitation += concat + teamMember.getTitleCache();
300 }
301
302 }
303 if (StringUtils.isBlank(shortCitation)){
304 shortCitation = authorTeam.getTitleCache();
305 }
306
307 }
308 if (reference.getDatePublished() != null) {
309 if (!StringUtils.isBlank(reference.getDatePublished().getFreeText())){
310 shortCitation = shortCitation + " (" + reference.getDatePublished().getFreeText() + ")";
311 }else if (!StringUtils.isBlank(reference.getYear()) ){
312 shortCitation = shortCitation + " (" + reference.getYear() + ")";
313 }
314 }
315
316 return shortCitation;
317 }
318
319 private static String concatString(Team team, List<Person> teamMembers, int i, String std_team_concatination, String final_team_concatination) {
320 String concat;
321 if (i <= 1){
322 concat = "";
323 }else if (i < teamMembers.size() || ( team.isHasMoreMembers() && i == teamMembers.size())){
324 concat = std_team_concatination;
325 }else{
326 concat = final_team_concatination;
327 }
328 return concat;
329 }
330
331
332 @Override
333 public String getNomenclaturalCache(Reference reference) {
334 return this.getNomenclaturalCitation(reference, null);
335 }
336
337 // ************************ TITLE CACHE SUBS ********************************************/
338
339 private String titleCacheRealInRef(Reference reference, boolean isAbbrev) {
340 ReferenceType type = reference.getType();
341 Reference inRef = reference.getInReference();
342 boolean hasInRef = (inRef != null);
343
344 String result;
345 //copy from InRefDefaultCacheStrategyBase
346 if (inRef != null){
347 result = CdmUtils.getPreferredNonEmptyString(inRef.getTitleCache(),
348 inRef.getAbbrevTitleCache(), isAbbrev, trim) ;
349 }else{
350 result = String.format("- undefined %s -", getUndefinedLabel(type));
351 }
352
353 //in
354 result = inSeparator + result;
355
356 //section title
357 String title = CdmUtils.getPreferredNonEmptyString(
358 reference.getTitle(), reference.getAbbrevTitle(), isAbbrev, trim);
359 if (title.length() > 0){
360 result = title + blank + result;
361 }
362
363 //section author
364 TeamOrPersonBase<?> thisRefTeam = reference.getAuthorship();
365 String thisRefAuthor = "";
366 if (thisRefTeam != null){
367 thisRefAuthor = CdmUtils.getPreferredNonEmptyString(thisRefTeam.getTitleCache(),
368 thisRefTeam.getNomenclaturalTitle(), isAbbrev, trim);
369 }
370 result = CdmUtils.concat(afterSectionAuthor, thisRefAuthor, result);
371
372 //date
373 if (reference.getDatePublished() != null && ! reference.getDatePublished().isEmpty()){
374 String thisRefDate = reference.getDatePublished().toString();
375 if (hasInRef && reference.getInBook().getDatePublished() != null){
376 VerbatimTimePeriod inRefDate = reference.getInReference().getDatePublished();
377 String inRefDateString = inRefDate.getYear();
378 if (isNotBlank(inRefDateString)){
379 int pos = StringUtils.lastIndexOf(result, inRefDateString);
380 if (pos > -1 ){
381 result = result.substring(0, pos) + thisRefDate + result.substring(pos + inRefDateString.length());
382 }else{
383 logger.warn("InRefDateString (" + inRefDateString + ") could not be found in result (" + result +")");
384 }
385 }else{
386 //avoid duplicate dots ('..')
387 String bYearSeparator = result.substring(result.length() -1).equals(beforeYear.substring(0, 1)) ? beforeYear.substring(1) : beforeYear;
388 result = result + bYearSeparator + thisRefDate + afterYear;
389 }
390 }else{
391 result = result + beforeYear + thisRefDate + afterYear;
392 }
393 }
394 return result;
395 }
396
397 private String titleCacheJournal(Reference reference, boolean isAbbrev) {
398 String result;
399 //copied from Journal
400
401 //title
402 result = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
403 reference.getAbbrevTitle(), isAbbrev, trim);
404
405 // //delete .
406 // while (result.endsWith(".")){
407 // result = result.substring(0, result.length()-1);
408 // }
409 // result = addYear(result, journal);
410
411 TeamOrPersonBase<?> team = reference.getAuthorship();
412 if (team != null){
413 String author = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
414 team.getNomenclaturalTitle(), isAbbrev, trim);
415 if (StringUtils.isNotBlank(author)){
416 result = author + afterAuthor + result;
417 }
418 }
419 return result;
420 }
421
422 private String titleCacheDefaultReference(Reference reference, boolean isAbbrev) {
423 String result;
424 //copied from ReferenceDefaultCacheStrategy
425 result = "";
426 String titel = CdmUtils.getPreferredNonEmptyString(reference.getTitle(),
427 reference.getAbbrevTitle(), isAbbrev, trim);
428 if (isNotBlank(titel)){
429 result = titel + blank;
430 }
431 //delete .
432 while (result.endsWith(".")){
433 result = result.substring(0, result.length()-1);
434 }
435
436 result = addYearReferenceDefault(result, reference);
437 TeamOrPersonBase<?> team = reference.getAuthorship();
438 if (team != null){
439 String author = CdmUtils.getPreferredNonEmptyString(team.getTitleCache(),
440 team.getNomenclaturalTitle(), isAbbrev, trim);
441 if (isNotBlank(author)){
442 result = author + afterAuthor + result;
443 }
444 }
445 return result;
446 }
447
448 // ******************************* HELPER *****************************************/
449 @Override
450 public String getBeforeMicroReference(){
451 return beforeMicroReference;
452 }
453
454 private String addYear(String string, Reference nomRef, boolean useFullDatePublished){
455 String result;
456 if (string == null){
457 return null;
458 }
459 String year = useFullDatePublished ? nomRef.getDatePublishedString() : nomRef.getYear();
460 if (isBlank(year)){
461 result = string + afterYear;
462 }else{
463 String concat = isBlank(string) ? "" : string.endsWith(".") ? " " : beforeYear;
464 result = string + concat + year + afterYear;
465 }
466 return result;
467 }
468
469 private String getTitleWithoutYearAndAuthor(Reference ref, boolean isAbbrev){
470 return TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthor(ref, isAbbrev);
471 }
472 private String getTitleWithoutYearAndAuthorGeneric(Reference ref, boolean isAbbrev){
473 return TitleWithoutYearAndAuthorHelper.getTitleWithoutYearAndAuthorGeneric(ref, isAbbrev);
474 }
475
476 private Object getUndefinedLabel(ReferenceType type) {
477 if (type == ReferenceType.BookSection){
478 return "book";
479 }else if (type == ReferenceType.Generic){
480 return "generic reference";
481 }else if (type == ReferenceType.Section){
482 return "in reference";
483 } else {
484 return type.getMessage();
485 }
486 }
487
488
489 /**
490 * Returns <code>true</code> if the type of the reference originally corresponded to a cache strategy
491 * which inherited from {@link InRefDefaultCacheStrategyBase} and in case of type {@link ReferenceType#Generic}
492 * if it really has an inreference (reference.getInreference() != null).
493 * @param reference
494 */
495 private boolean isRealInRef(Reference reference) {
496 ReferenceType type = (reference.getType());
497 if (type == null){
498 return false;
499 }else if (type == ReferenceType.BookSection || type == ReferenceType.Section){
500 return true;
501 }else if (type == ReferenceType.Generic){
502 return reference.getInReference() != null;
503 }else{
504 return false;
505 }
506 }
507
508 /**
509 * Returns <code>true</code> if the type of the reference originally corresponded to a cache strategy
510 * which inherited from {@link NomRefDefaultCacheStrategyBase}.
511 * @param type
512 */
513 protected static boolean isNomRef(ReferenceType type){
514 switch (type){
515 case Article:
516 case Book:
517 case BookSection:
518 case CdDvd:
519 case Generic:
520 case Section:
521 case Thesis:
522 case WebPage:
523 return true;
524
525 case Journal:
526 default:
527 return false;
528 }
529 }
530
531 /**
532 * Returns year information as originally computed by {@link ReferenceDefaultCacheStrategy}
533 */
534 private String addYearReferenceDefault(String string, Reference ref){
535 String result;
536 if (string == null){
537 return null;
538 }
539 String year = CdmUtils.Nz(ref.getYear());
540 if ("".equals(year)){
541 result = string + afterYear;
542 }else{
543 result = string.trim() + beforeYear + year + afterYear;
544 }
545 return result;
546 }
547
548
549 // ********************* Nomenclatural title ***************************************/
550
551 @Override
552 public String getNomenclaturalCitation(Reference reference, String microReference) {
553 if (reference.isProtectedAbbrevTitleCache()){
554 String cache = reference.getAbbrevTitleCache();
555 return handleDetailAndYearForProtected(reference, cache, microReference);
556
557 }
558 String result = getTokenizedNomenclaturalTitel(reference);
559 //if no data is available and only titleCache is protected take the protected title
560 //this is to avoid empty cache if someone forgets to set also the abbrevTitleCache
561 //we need to think about handling protected not separate for abbrevTitleCache and titleCache
562 if (result.equals(INomenclaturalReference.MICRO_REFERENCE_TOKEN) && reference.isProtectedTitleCache() ){
563 String cache = reference.getTitleCache();
564 return handleDetailAndYearForProtected(reference, cache, microReference);
565 }
566
567 microReference = Nz(microReference);
568 if (StringUtils.isNotBlank(microReference)){
569 microReference = getBeforeMicroReference() + microReference;
570 if (microReference.endsWith(".") && result.contains(INomenclaturalReference.MICRO_REFERENCE_TOKEN + ".") ){
571 microReference = microReference.substring(0, microReference.length() - 1);
572 }
573 }
574 result = replaceMicroRefToken(microReference, result);
575 if (result.startsWith(". ")){ //only year available, remove '. '
576 result = result.substring(2);
577 }
578 return result;
579 }
580
581 private String handleDetailAndYearForProtected(Reference nomenclaturalReference, String cache, String microReference) {
582 String microRef = isNotBlank(microReference) ? getBeforeMicroReference() + microReference : "";
583 if (cache == null){
584 logger.warn("Cache is null. This should never be the case.");
585 cache = "";
586 }
587 String result = cache + (cache.contains(microRef) ? "" : microRef);
588
589 String date = nomenclaturalReference.getDatePublishedString();
590 if (isNotBlank(date) && ! result.contains(date)){
591 result = result + beforeYear + date;
592 }
593 return result;
594 }
595
596 /**
597 * Returns the nomenclatural title with micro reference represented as token
598 * which can later be replaced by the real data.
599 *
600 * @see INomenclaturalReference#MICRO_REFERENCE_TOKEN
601 *
602 * @param ref The reference
603 * @return
604 */
605 private String getTokenizedNomenclaturalTitel(Reference ref) {
606 if (isRealInRef(ref)){
607 return getTokenizedNomenclaturalTitelInRef(ref);
608 }else{
609 String result = getTitleWithoutYearAndAuthor(ref, true);
610 result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
611 result = addYear(result, ref, true);
612 return result;
613 }
614 }
615
616 private String getTokenizedNomenclaturalTitelInRef(Reference thisRef) {
617 if (thisRef == null){
618 return null;
619 }
620
621 Reference inRef = CdmBase.deproxy(thisRef.getInReference(), Reference.class);
622 if (inRef != null && inRef.getInReference() != null && thisRef.getType() == ReferenceType.Section){
623 //this is a reference of type Section which has a in-in-Ref
624 //TODO maybe we do not need to restrict to type=Section only
625 return this.getTokenizedNomenclaturalTitelInInRef(thisRef);
626 }
627
628 String result;
629 //use generics's publication date if it exists
630 if (inRef == null || (thisRef.hasDatePublished() ) ){
631 getTitleWithoutYearAndAuthorGeneric(inRef, true);
632 result = inRef == null ? "" : getTitleWithoutYearAndAuthorGeneric(inRef, true);
633 //added //TODO unify with non-inRef references formatting
634
635 if (isNotBlank(thisRef.getVolume())){
636 result = result + " " + thisRef.getVolume();
637 }
638 //TODO series / edition
639
640 //end added
641 result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
642 result = addYear(result, thisRef, true);
643 }else{
644 //else use inRefs's publication date
645 result = inRef.getNomenclaturalCitation(INomenclaturalReference.MICRO_REFERENCE_TOKEN);
646 if (result != null){
647 result = result.replace(beforeMicroReference + INomenclaturalReference.MICRO_REFERENCE_TOKEN, INomenclaturalReference.MICRO_REFERENCE_TOKEN);
648 }
649 }
650 //FIXME: vol. etc., http://dev.e-taxonomy.eu/trac/ticket/2862
651
652 result = getInRefAuthorPart(thisRef.getInReference(), afterInRefAuthor) + result;
653 result = "in " + result;
654 return result;
655 }
656
657 /**
658 * For handling in-in-Ref case.
659 * Must only be called if a reference has inRef and inInRef
660 * @param section
661 * @return
662 */
663 private String getTokenizedNomenclaturalTitelInInRef(Reference ref) {
664 String result;
665
666 Reference inRef = CdmBase.deproxy(ref.getInReference(), Reference.class);
667 Reference inInRef = CdmBase.deproxy(inRef.getInReference(), Reference.class);
668
669 if (! isNomRef(inInRef.getType())){
670 if (! isNomRef(inRef.getType())){
671 logger.warn("Neither inReference nor inInReference is a "
672 + " nomenclatural reference. This is not correct or not handled yet."
673 + " Generic titleWithoutYearAndAuthor used instead");
674 result = getTitleWithoutYearAndAuthorGeneric(inInRef, true);
675 //FIXME: vol. etc., http://dev.e-taxonomy.eu/trac/ticket/2862 (comment taken from super.getTokenizedNomenclaturalTitel())
676 }else{
677 result = getTitleWithoutYearAndAuthor(inRef, true);
678 }
679 }else{
680 result = getTitleWithoutYearAndAuthor(inInRef, true);
681 }
682 result += INomenclaturalReference.MICRO_REFERENCE_TOKEN;
683
684 Reference dataReference = (ref.hasDatePublished() ? ref : inRef.hasDatePublished() ? inRef : inInRef);
685
686 result = addYear(result, dataReference, true);
687
688 result = getInRefAuthorPart(inInRef, afterInRefAuthor) + result;
689 if (! result.startsWith("in ")){
690 result = "in " + result;
691 }
692 return result;
693 }
694
695 private String getInRefAuthorPart(Reference book, String seperator){
696 if (book == null){
697 return "";
698 }
699 TeamOrPersonBase<?> team = book.getAuthorship();
700 String result = Nz( team == null ? "" : team.getNomenclaturalTitle());
701 if (! result.trim().equals("")){
702 result = result + seperator;
703 }
704 return result;
705 }
706
707 private String replaceMicroRefToken(String microReference, String string) {
708 int index = string.indexOf(INomenclaturalReference.MICRO_REFERENCE_TOKEN);
709
710 if (index > -1){
711 String before = string.substring(0, index);
712 String after = string.substring(index + INomenclaturalReference.MICRO_REFERENCE_TOKEN.length() );
713 String localMicroReference = microReference.trim(); //needed ?
714 if (after.length() > 0){
715 if ( ("".equals(localMicroReference) && before.endsWith(after.substring(0,1)) || localMicroReference.endsWith(after.substring(0,1)))){
716 after = after.substring(1);
717 }
718 }
719 String result = before + localMicroReference + after;
720 return result;
721 }else{
722 return string;
723 }
724 }
725
726 // *************************** EXTERNAL USE *******************************************/
727
728 public static String putAuthorToEndOfString(String referenceTitleCache, String authorTitleCache) {
729 if(authorTitleCache != null){
730 referenceTitleCache = referenceTitleCache.replace(authorTitleCache + ", ", "");
731 referenceTitleCache += " - " + authorTitleCache;
732 }
733 return referenceTitleCache;
734 }
735 }