cleanup
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / reference / Reference.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
10 package eu.etaxonomy.cdm.model.reference;
11
12 import java.beans.PropertyChangeEvent;
13 import java.beans.PropertyChangeListener;
14 import java.net.URI;
15 import java.util.List;
16
17 import javax.persistence.Basic;
18 import javax.persistence.Column;
19 import javax.persistence.Embedded;
20 import javax.persistence.Entity;
21 import javax.persistence.FetchType;
22 import javax.persistence.Inheritance;
23 import javax.persistence.InheritanceType;
24 import javax.persistence.Lob;
25 import javax.persistence.ManyToOne;
26 import javax.persistence.Transient;
27 import javax.validation.constraints.NotNull;
28 import javax.validation.constraints.Pattern;
29 import javax.xml.bind.annotation.XmlAccessType;
30 import javax.xml.bind.annotation.XmlAccessorType;
31 import javax.xml.bind.annotation.XmlAttribute;
32 import javax.xml.bind.annotation.XmlElement;
33 import javax.xml.bind.annotation.XmlIDREF;
34 import javax.xml.bind.annotation.XmlRootElement;
35 import javax.xml.bind.annotation.XmlSchemaType;
36 import javax.xml.bind.annotation.XmlTransient;
37 import javax.xml.bind.annotation.XmlType;
38 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
39
40 import org.apache.commons.lang.StringUtils;
41 import org.apache.log4j.Logger;
42 import org.hibernate.annotations.Cascade;
43 import org.hibernate.annotations.CascadeType;
44 import org.hibernate.annotations.Table;
45 import org.hibernate.annotations.Type;
46 import org.hibernate.envers.Audited;
47 import org.hibernate.search.annotations.Analyze;
48 import org.hibernate.search.annotations.Field;
49 import org.hibernate.search.annotations.FieldBridge;
50 import org.hibernate.search.annotations.IndexedEmbedded;
51 import org.joda.time.DateTime;
52
53 import eu.etaxonomy.cdm.common.DOI;
54 import eu.etaxonomy.cdm.hibernate.search.DateTimeBridge;
55 import eu.etaxonomy.cdm.hibernate.search.DoiBridge;
56 import eu.etaxonomy.cdm.jaxb.DateTimeAdapter;
57 import eu.etaxonomy.cdm.model.agent.Institution;
58 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
59 import eu.etaxonomy.cdm.model.common.IIntextReferenceTarget;
60 import eu.etaxonomy.cdm.model.common.TimePeriod;
61 import eu.etaxonomy.cdm.model.common.VerbatimTimePeriod;
62 import eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity;
63 import eu.etaxonomy.cdm.model.name.TaxonName;
64 import eu.etaxonomy.cdm.strategy.cache.reference.DefaultReferenceCacheStrategy;
65 import eu.etaxonomy.cdm.strategy.cache.reference.INomenclaturalReferenceCacheStrategy;
66 import eu.etaxonomy.cdm.strategy.match.Match;
67 import eu.etaxonomy.cdm.strategy.match.MatchMode;
68 import eu.etaxonomy.cdm.strategy.merge.Merge;
69 import eu.etaxonomy.cdm.strategy.merge.MergeMode;
70 import eu.etaxonomy.cdm.strategy.parser.ParserProblem;
71 import eu.etaxonomy.cdm.validation.Level2;
72 import eu.etaxonomy.cdm.validation.Level3;
73 import eu.etaxonomy.cdm.validation.annotation.InReference;
74 import eu.etaxonomy.cdm.validation.annotation.NoRecursiveInReference;
75 import eu.etaxonomy.cdm.validation.annotation.NullOrNotEmpty;
76 import eu.etaxonomy.cdm.validation.annotation.ReferenceCheck;
77
78 /**
79 * The class for references (information sources). Originally
80 * an abstract class with many subclasses. Not it is only
81 * one class implementing many interfaces for safe use.
82 * <P>
83 * This class corresponds to: <ul>
84 * <li> PublicationCitation according to the TDWG ontology
85 * <li> Publication according to the TCS
86 * <li> Reference according to the ABCD schema
87 * </ul>
88 *
89 * @author m.doering
90 * @since 08-Nov-2007 13:06:47
91 */
92 @XmlAccessorType(XmlAccessType.FIELD)
93 @XmlType(name = "Reference", propOrder = {
94 "type",
95 "uri",
96 "abbrevTitleCache",
97 "protectedAbbrevTitleCache",
98 "nomenclaturallyRelevant",
99 "authorship",
100 "referenceAbstract",
101 "title",
102 "abbrevTitle",
103 "editor",
104 "volume",
105 "pages",
106 "edition",
107 "isbn",
108 "issn",
109 "doi",
110 "seriesPart",
111 "datePublished",
112 "publisher",
113 "placePublished",
114 "institution",
115 "school",
116 "organization",
117 "inReference",
118 "accessed",
119 "lastRetrieved",
120 "externalId",
121 "externalLink",
122 "authorityType"
123 })
124 @XmlRootElement(name = "Reference")
125 @Entity
126 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
127 @Audited
128 @Table(appliesTo="Reference", indexes = { @org.hibernate.annotations.Index(name = "ReferenceTitleCacheIndex", columnNames = { "titleCache" }) })
129 //@InReference(groups=Level3.class)
130 @ReferenceCheck(groups=Level2.class)
131 @InReference(groups=Level3.class)
132 @NoRecursiveInReference(groups=Level3.class) //may become Level1 in future #
133 public class Reference
134 extends IdentifiableMediaEntity<INomenclaturalReferenceCacheStrategy>
135 implements IArticle, IBook, IPatent, IDatabase, IJournal, IBookSection,ICdDvd,
136 IGeneric,IInProceedings, IProceedings, IPrintSeries, IReport,
137 IThesis,IWebPage, IPersonalCommunication,
138 INomenclaturalReference, IReference, IIntextReferenceTarget,
139 Cloneable {
140
141 private static final long serialVersionUID = -2034764545042691295L;
142 private static final Logger logger = Logger.getLogger(Reference.class);
143
144 @XmlAttribute(name ="type")
145 @Column(name="refType")
146 @NotNull
147 @Type(type = "eu.etaxonomy.cdm.hibernate.EnumUserType",
148 parameters = {@org.hibernate.annotations.Parameter(name = "enumClass", value = "eu.etaxonomy.cdm.model.reference.ReferenceType")}
149 )
150 @Audited
151 protected ReferenceType type;
152
153 //Title of the reference
154 @XmlElement(name ="Title" )
155 @Column(length=4096, name="title")
156 @Lob
157 @Field
158 @Match(MatchMode.EQUAL_REQUIRED) //TODO correct? was EQUAL_REQUIRED before, but with abbrevTitle this is not realistic anymore
159 //TODO Val #3379
160 // @NullOrNotEmpty
161 private String title;
162
163 //Title of the reference
164 @XmlElement(name ="AbbrevTitle" )
165 @Field
166 @Match(MatchMode.EQUAL) //TODO check if this is correct
167 @NullOrNotEmpty
168 @Column(length=255)
169 private String abbrevTitle;
170
171 //Title of the reference
172 @XmlElement(name ="AbbrevTitleCache" )
173 @Field
174 @Match(MatchMode.CACHE)
175 //TODO Val #3379
176 // @NotNull
177 @Column(length=1024)
178 private String abbrevTitleCache;
179
180 @XmlElement(name = "protectedAbbrevTitleCache")
181 @Merge(MergeMode.OR)
182 private boolean protectedAbbrevTitleCache;
183
184 //********************************************************/
185
186
187 @XmlElement(name = "Editor")
188 @Field
189 //TODO Val #3379
190 // @NullOrNotEmpty
191 @Column(length=255)
192 protected String editor;
193
194 @XmlElement(name = "Volume")
195 @Field
196 //TODO Val #3379
197 // @NullOrNotEmpty
198 @Column(length=255)
199 protected String volume;
200
201 @XmlElement(name = "Pages")
202 @Field
203 //TODO Val #3379
204 // @NullOrNotEmpty
205 @Column(length=255)
206 protected String pages;
207
208 @XmlElement(name = "Edition")
209 @Field
210 //TODO Val #3379
211 // @NullOrNotEmpty
212 @Column(length=255)
213 protected String edition;
214
215 @XmlElement(name = "ISBN")
216 @Field
217 //TODO Val #3379
218 // @NullOrNotEmpty
219 @Column(length=255)
220 @Pattern(regexp = "(?=.{13}$)\\d{1,5}([- ])\\d{1,7}\\1\\d{1,6}\\1(\\d|X)$", groups = Level2.class, message = "{eu.etaxonomy.cdm.model.reference.Reference.isbn.message}")
221 protected String isbn;
222
223 @XmlElement(name = "Doi")
224 @Field
225 @FieldBridge(impl = DoiBridge.class)
226 @Type(type="doiUserType")
227 @Column(length=DOI.MAX_LENGTH)
228 protected DOI doi;
229
230
231 @XmlElement(name = "ISSN")
232 @Field
233 //TODO Val #3379
234 // @NullOrNotEmpty
235 @Column(length=255)
236 @Pattern(regexp = "(?=.{9}$)\\d{4}([- ])\\d{4} (\\d|X)$", groups = Level2.class, message = "{eu.etaxonomy.cdm.model.reference.Reference.issn.message}")
237 protected String issn;
238
239 @XmlElement(name = "SeriesPart")
240 @Field
241 //TODO Val #3379
242 // @NullOrNotEmpty
243 @Column(length=255)
244 protected String seriesPart;
245
246 @XmlElement(name = "Organization")
247 @Field
248 //TODO Val #3379
249 // @NullOrNotEmpty
250 @Column(length=255)
251 protected String organization;
252
253 @XmlElement(name = "Publisher")
254 @Field
255 //TODO Val #3379
256 // @NullOrNotEmpty
257 @Column(length=255)
258 protected String publisher;
259
260
261 @XmlElement(name = "PlacePublished")
262 @Field
263 //TODO Val #3379
264 // @NullOrNotEmpty
265 @Column(length=255)
266 protected String placePublished;
267
268 @XmlElement(name = "Institution")
269 @XmlIDREF
270 @XmlSchemaType(name = "IDREF")
271 @ManyToOne(fetch = FetchType.LAZY)
272 @IndexedEmbedded
273 @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
274 protected Institution institution;
275
276 @XmlElement(name = "School")
277 @XmlIDREF
278 @XmlSchemaType(name = "IDREF")
279 @ManyToOne(fetch = FetchType.LAZY)
280 @IndexedEmbedded
281 @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
282 protected Institution school;
283
284 @XmlElement(name = "InReference")
285 @XmlIDREF
286 @XmlSchemaType(name = "IDREF")
287 @ManyToOne(fetch = FetchType.LAZY)
288 // @IndexedEmbedded
289 @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
290 // @InReference(groups=Level2.class)
291 protected Reference inReference;
292
293 //********************************************************/
294
295 //The date range assigned to the reference. ISO Date range like. Flexible, year can be left out, etc
296 @XmlElement(name ="DatePublished" )
297 @Embedded
298 @IndexedEmbedded
299 private VerbatimTimePeriod datePublished = VerbatimTimePeriod.NewVerbatimInstance();
300
301 //#5258
302 @XmlElement (name = "Accessed", type= String.class)
303 @XmlJavaTypeAdapter(DateTimeAdapter.class)
304 @Type(type="dateTimeUserType")
305 @Basic(fetch = FetchType.LAZY)
306 @Match(MatchMode.EQUAL)
307 @FieldBridge(impl = DateTimeBridge.class)
308 private DateTime accessed;
309
310 @XmlElement(name ="Abstract" )
311 @Column(length=65536, name="referenceAbstract")
312 @Lob
313 @Field
314 //TODO Val #3379
315 // @NullOrNotEmpty
316 private String referenceAbstract; //abstract is a reserved term in Java
317
318
319 //URIs like DOIs, LSIDs or Handles for this reference
320 @XmlElement(name = "URI")
321 @Field(analyze = Analyze.NO)
322 @Type(type="uriUserType")
323 private URI uri;
324
325 //flag to subselect only references that could be useful for nomenclatural citations.
326 //If a reference is used as a
327 //nomenclatural reference in a name this flag should be automatically set
328 @XmlElement(name = "IsNomenclaturallyRelevant")
329 @Merge(MergeMode.OR)
330 private boolean nomenclaturallyRelevant;
331
332 @XmlElement(name = "Authorship")
333 @XmlIDREF
334 @XmlSchemaType(name = "IDREF")
335 @ManyToOne(fetch = FetchType.LAZY)
336 @IndexedEmbedded
337 @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
338 private TeamOrPersonBase<?> authorship;
339
340 @XmlAttribute
341 @Match(MatchMode.IGNORE)
342 private int parsingProblem = 0;
343
344 @XmlAttribute
345 @Match(MatchMode.IGNORE)
346 private int problemStarts = -1;
347
348 @XmlAttribute
349 @Match(MatchMode.IGNORE)
350 private int problemEnds = -1;
351
352 @Transient
353 @XmlAttribute
354 @Match(MatchMode.IGNORE)
355 private boolean cacheStrategyRectified = false;
356
357 //attributes for externally managed
358
359 // @XmlElement (name = "LastRetrieved", type= String.class)
360 @XmlJavaTypeAdapter(DateTimeAdapter.class)
361 @Type(type="dateTimeUserType")
362 //TODO needed??
363 @Basic(fetch = FetchType.LAZY)
364 private DateTime lastRetrieved;
365
366 @XmlElement(name ="ExternalId" )
367 // @Field
368 // @Match(MatchMode.EQUAL) //TODO check if this is correct
369 @NullOrNotEmpty
370 @Column(length=255)
371 private String externalId;
372
373 //Actionable link on e.g. on a webservice
374 @XmlElement(name = "ExternalLink")
375 @Field(analyze = Analyze.NO)
376 @Type(type="uriUserType")
377 private URI externalLink;
378
379 @XmlAttribute(name ="authority")
380 @Column(name="authorityType", length=10)
381 @Type(type = "eu.etaxonomy.cdm.hibernate.EnumUserType",
382 parameters = {@org.hibernate.annotations.Parameter(name = "enumClass", value = "eu.etaxonomy.cdm.model.reference.AuthorityType")}
383 )
384 // @NotNull
385 private AuthorityType authorityType;
386
387 // *********************** CONSTRUCTOR ************************/
388
389 protected Reference(){
390 this(ReferenceType.Generic); //just in case someone uses constructor
391 }
392
393 protected Reference(ReferenceType type) {
394 super();
395 if (type == null){
396 this.type = ReferenceType.Generic;
397 } else{
398 this.type = type;
399 }
400 this.setCacheStrategy(DefaultReferenceCacheStrategy.NewInstance());
401 }
402
403 // *********************** LISTENER ************************/
404
405
406 @Override
407 public void initListener(){
408 PropertyChangeListener listener = new PropertyChangeListener() {
409 @Override
410 public void propertyChange(PropertyChangeEvent ev) {
411 if (!ev.getPropertyName().equals("titleCache") && !ev.getPropertyName().equals("abbrevTitleCache") && !ev.getPropertyName().equals("cacheStrategy")){
412 if (! isProtectedTitleCache()){
413 titleCache = null;
414 }
415 if (! isProtectedAbbrevTitleCache()){
416 abbrevTitleCache = null;
417 }
418 }
419 }
420 };
421 addPropertyChangeListener(listener);
422 }
423
424
425 //*************************** GETTER / SETTER ******************************************/
426
427
428
429 // @Transient - must not be transient, since this property needs to to be included in all serializations produced by the remote layer
430 @Override
431 public String getTitleCache(){
432 String result = super.getTitleCache();
433 if (isBlank(result)){
434 this.titleCache = this.getAbbrevTitleCache(true);
435 }
436 return titleCache;
437 }
438
439 @Override
440 public String getAbbrevTitleCache() {
441 return getAbbrevTitleCache(false);
442 }
443
444 /**
445 * Implements {@link #getAbbrevTitleCache()} but allows to
446 * avoid never ending recursions if both caches are empty
447 * avoidRecursion should only be <code>true</code> if called
448 * by {@link #getTitleCache()}
449 * @param avoidRecursion
450 * @return
451 */
452 private String getAbbrevTitleCache(boolean avoidRecursion) {
453 if (protectedAbbrevTitleCache){
454 return this.abbrevTitleCache;
455 }
456 // is reference dirty, i.e. equal NULL?
457 if (abbrevTitleCache == null){
458 this.abbrevTitleCache = generateAbbrevTitle();
459 this.abbrevTitleCache = getTruncatedCache(this.abbrevTitleCache) ;
460 }
461 if (isBlank(abbrevTitleCache) && !avoidRecursion){
462 this.abbrevTitleCache = this.getTitleCache();
463 }
464 return abbrevTitleCache;
465 }
466
467
468 @Override
469 @Deprecated
470 public void setAbbrevTitleCache(String abbrevTitleCache) {
471 this.abbrevTitleCache = abbrevTitleCache;
472 }
473
474 @Override
475 public void setAbbrevTitleCache(String abbrevTitleCache, boolean isProtected) {
476 this.protectedAbbrevTitleCache = isProtected;
477 setAbbrevTitleCache(abbrevTitleCache);
478 }
479
480 @Override
481 public boolean isProtectedAbbrevTitleCache() {
482 return protectedAbbrevTitleCache;
483 }
484
485 @Override
486 public void setProtectedAbbrevTitleCache(boolean protectedAbbrevTitleCache) {
487 this.protectedAbbrevTitleCache = protectedAbbrevTitleCache;
488 }
489
490 @Override
491 public String getAbbrevTitle() {
492 return abbrevTitle;
493 }
494
495 @Override
496 public void setAbbrevTitle(String abbrevTitle) {
497 this.abbrevTitle = StringUtils.isBlank(abbrevTitle) ? null : abbrevTitle;
498 }
499
500
501 @Override
502 public String getEditor() {
503 return editor;
504 }
505
506
507 @Override
508 public void setEditor(String editor) {
509 this.editor = StringUtils.isBlank(editor)? null : editor;
510 }
511
512 @Override
513 public String getVolume() {
514 return volume;
515 }
516
517 @Override
518 public void setVolume(String volume) {
519 this.volume = StringUtils.isBlank(volume)? null : volume;
520 }
521
522 @Override
523 public String getPages() {
524 return pages;
525 }
526
527 @Override
528 public void setPages(String pages) {
529 this.pages = StringUtils.isBlank(pages)? null : pages;
530 }
531
532 @Override
533 public String getEdition() {
534 return edition;
535 }
536
537 @Override
538 public void setEdition(String edition) {
539 this.edition = StringUtils.isBlank(edition)? null : edition;
540 }
541
542 @Override
543 public String getIsbn() {
544 return isbn;
545 }
546
547 @Override
548 public void setIsbn(String isbn) {
549 this.isbn = StringUtils.isBlank(isbn)? null : isbn;
550 }
551
552 @Override
553 public String getIssn() {
554 return issn;
555 }
556
557 @Override
558 public void setIssn(String issn) {
559 this.issn = StringUtils.isBlank(issn)? null : issn;
560 }
561
562 @Override
563 public DOI getDoi() {
564 return doi;
565 }
566 @Override
567 public void setDoi(DOI doi) {
568 this.doi = doi;
569 }
570 /**
571 * Convenience method to retrieve doi as string
572 */
573 @Transient @XmlTransient @java.beans.Transient
574 public String getDoiString() {
575 return doi == null? null : doi.toString();
576 }
577
578 @Override
579 public String getSeriesPart() {
580 return seriesPart;
581 }
582 @Override
583 public void setSeriesPart(String seriesPart) {
584 this.seriesPart = StringUtils.isBlank(seriesPart)? null : seriesPart;
585 }
586
587 @Override
588 public String getOrganization() {
589 return organization;
590 }
591
592 @Override
593 public void setOrganization(String organization) {
594 this.organization = StringUtils.isBlank(organization)? null : organization;
595 }
596
597 @Override
598 public String getPublisher() {
599 return publisher;
600 }
601
602 @Override
603 public void setPublisher(String publisher) {
604 this.publisher = StringUtils.isBlank(publisher)? null : publisher;
605 }
606
607 @Override
608 public void setPublisher(String publisher, String placePublished){
609 this.publisher = publisher;
610 this.placePublished = placePublished;
611 }
612
613 @Override
614 public String getPlacePublished() {
615 return placePublished;
616 }
617
618 @Override
619 public void setPlacePublished(String placePublished) {
620 this.placePublished = StringUtils.isBlank(placePublished)? null: placePublished;
621 }
622
623 @Override
624 public Institution getInstitution() {
625 return institution;
626 }
627
628 @Override
629 public void setInstitution(Institution institution) {
630 this.institution = institution;
631 }
632
633 @Override
634 public Institution getSchool() {
635 return school;
636 }
637
638 @Override
639 public void setSchool(Institution school) {
640 this.school = school;
641 }
642
643 @Override
644 public Reference getInReference() {
645 return inReference;
646 }
647
648 @Override
649 public void setInReference(Reference inReference) {
650 this.inReference = inReference;
651 }
652
653 @Override
654 public void setType(ReferenceType type) {
655 if (type == null){
656 this.type = ReferenceType.Generic;
657 } else{
658 this.type = type;
659 }
660 }
661 @Override
662 public ReferenceType getType() {
663 return type;
664 }
665
666 /**
667 * Whether this reference is of the given type
668 *
669 * @param type
670 * @return
671 */
672 @Override
673 public boolean isOfType(ReferenceType type){
674 return type == getType();
675 }
676
677 /**
678 * Returns a string representing the title of <i>this</i> reference. If a
679 * reference has different titles (for instance abbreviated and not
680 * abbreviated) then for each title a new instance must be created.
681 *
682 * @return the title string of <i>this</i> reference
683 * @see #getCitation()
684 */
685 @Override
686 public String getTitle(){
687 return this.title;
688 }
689 /**
690 * @see #getTitle()
691 */
692 @Override
693 public void setTitle(String title){
694 this.title = StringUtils.isBlank(title)? null : title;
695 }
696
697 /**
698 * Returns the date (mostly only the year) of publication / creation of
699 * <i>this</i> reference.
700 */
701 @Override
702 public VerbatimTimePeriod getDatePublished(){
703 return this.datePublished;
704 }
705 /**
706 * @see #getDatePublished()
707 */
708 @Override
709 public void setDatePublished(VerbatimTimePeriod datePublished){
710 this.datePublished = datePublished;
711 }
712 @Override
713 @Transient
714 public void setDatePublished(TimePeriod datePublished){
715 setDatePublished(VerbatimTimePeriod.toVerbatim(datePublished));
716 }
717
718 public boolean hasDatePublished(){
719 boolean result = ! ( (this.datePublished == null) || StringUtils.isBlank(datePublished.toString()));
720 return result;
721 }
722
723
724 @Override
725 public DateTime getAccessed() {
726 return accessed;
727 }
728
729 @Override
730 public void setAccessed(DateTime accessed) {
731 this.accessed = accessed;
732 }
733
734 /**
735 * Returns the {@link eu.etaxonomy.cdm.model.agent.TeamOrPersonBase author (team)} who created the
736 * content of <i>this</i> reference.
737 *
738 * @return the author (team) of <i>this</i> reference
739 * @see eu.etaxonomy.cdm.model.agent.TeamOrPersonBase
740 */
741 @Override
742 public TeamOrPersonBase getAuthorship(){
743 return this.authorship;
744 }
745
746 /**
747 * @see #getAuthorship()
748 */
749 @Override
750 public void setAuthorship(TeamOrPersonBase authorship){
751 this.authorship = authorship;
752 }
753
754 /**
755 * Returns the Uniform Resource Identifier (URI) corresponding to <i>this</i>
756 * reference. An URI is a string of characters used to identify a resource
757 * on the Internet.
758 *
759 * @return the URI of <i>this</i> reference
760 */
761 @Override
762 public URI getUri(){
763 return this.uri;
764 }
765 /**
766 * @see #getUri()
767 */
768 @Override
769 public void setUri(URI uri){
770 this.uri = uri;
771 }
772
773 /**
774 * @return the referenceAbstract
775 */
776 @Override
777 public String getReferenceAbstract() {
778 return referenceAbstract;
779 }
780
781 /**
782 * @param referenceAbstract the referenceAbstract to set
783 */
784 @Override
785 public void setReferenceAbstract(String referenceAbstract) {
786 this.referenceAbstract = StringUtils.isBlank(referenceAbstract)? null : referenceAbstract;
787 }
788
789
790 /**
791 * Returns "true" if the isNomenclaturallyRelevant flag is set. This
792 * indicates that a {@link TaxonName taxon name} has been originally
793 * published in <i>this</i> reference following the rules of a
794 * {@link eu.etaxonomy.cdm.model.name.NomenclaturalCode nomenclature code} and is therefore used for
795 * nomenclatural citations. This flag will be set as soon as <i>this</i>
796 * reference is used as a nomenclatural reference for any taxon name.<BR>
797 * FIXME what happens if the only taxon name referencing this reference is not
798 * any longer using this reference as a nomenclatural reference. How does the
799 * reference get informed about the fact that it is not nomenclaturally relevant
800 * anymore?
801 */
802 public boolean isNomenclaturallyRelevant(){
803 return this.nomenclaturallyRelevant;
804 }
805
806 /**
807 * @see #isNomenclaturallyRelevant()
808 */
809 public void setNomenclaturallyRelevant(boolean nomenclaturallyRelevant){
810 this.nomenclaturallyRelevant = nomenclaturallyRelevant;
811 }
812
813
814 //**************************************************** /
815
816 @Transient
817 @Override
818 public void setTitleCaches(String cache){
819 this.setAbbrevTitleCache(cache, true);
820 this.setTitleCache(cache, true);
821 }
822
823
824 /**
825 * Returns a formatted string containing the entire reference citation,
826 * including authors, corresponding to <i>this</i> reference.
827 *
828 * @see #generateTitle()
829 */
830 // TODO implement
831 @Transient
832 public String getCitation(){
833 if (getCacheStrategy() == null){
834 logger.warn("No CacheStrategy defined for "+ this.getClass() + ": " + this.getUuid());
835 return null;
836 }else{
837 return getCacheStrategy().getTitleCache(this);
838 }
839 }
840
841
842 @Override
843 public String generateTitle() {
844 return super.generateTitle();
845 }
846
847 public String generateAbbrevTitle() {
848 return getCacheStrategy().getFullAbbrevTitleString(this);
849 }
850
851 /**
852 * Returns a string representation for the year of publication / creation
853 * of <i>this</i> reference. If the {@link #getDatePublished() datePublished}
854 * of this reference contains more date information then (starting) year
855 * only the year is returned.
856 * than attribute.
857 */
858 @Override
859 @Transient
860 public String getYear(){
861 TimePeriod datePublished = this.getDatePublished();
862 if (datePublished != null ){
863 String result = getDatePublished().getYear();
864 return result;
865 }else{
866 return null;
867 }
868 }
869
870 /**
871 * Convenience method that returns a string representation for the publication date / creation
872 * of <i>this</i> reference. The string is obtained by
873 * {@link #getDatePublished()#toString() the string representation
874 * of the date published}.
875 */
876 @Transient
877 public String getDatePublishedString(){
878 TimePeriod datePublished = this.getDatePublished();
879 if (datePublished != null ){
880 return getDatePublished().toString();
881 }else{
882 return null;
883 }
884 }
885
886 /**
887 * Convenience method that returns a string representation for the publication date / creation
888 * of <i>this</i> reference. The string is obtained by
889 * {@link #getDatePublished()#toString() the string representation
890 * of the date published}.
891 */
892 @Transient
893 public String getTimePeriodPublishedString(){
894 TimePeriod datePublished = this.getDatePublished();
895 if (datePublished != null ){
896 return getDatePublished().getTimePeriod();
897 }else{
898 return null;
899 }
900 }
901
902
903
904 @Override
905 public int getParsingProblem(){
906 return this.parsingProblem;
907 }
908
909 @Override
910 public void setParsingProblem(int parsingProblem){
911 this.parsingProblem = parsingProblem;
912 }
913
914 @Override
915 public boolean hasProblem(){
916 return parsingProblem != 0;
917 }
918
919 @Override
920 public boolean hasProblem(ParserProblem problem) {
921 return getParsingProblems().contains(problem);
922 }
923
924 @Override
925 public int getProblemStarts(){
926 return this.problemStarts;
927 }
928
929 @Override
930 public void setProblemStarts(int start) {
931 this.problemStarts = start;
932 }
933
934 @Override
935 public int getProblemEnds(){
936 return this.problemEnds;
937 }
938
939 @Override
940 public void setProblemEnds(int end) {
941 this.problemEnds = end;
942 }
943
944 @Override
945 public void addParsingProblem(ParserProblem warning){
946 parsingProblem = ParserProblem.addProblem(parsingProblem, warning);
947 }
948
949 @Override
950 public void removeParsingProblem(ParserProblem problem) {
951 parsingProblem = ParserProblem.removeProblem(parsingProblem, problem);
952 }
953
954 @Override
955 @Transient
956 public List<ParserProblem> getParsingProblems() {
957 return ParserProblem.warningList(this.parsingProblem);
958 }
959
960
961 @Override
962 @Transient
963 public String getNomenclaturalCitation(String microReference) {
964 String typeName = this.getType()== null ? "(no type defined)" : this.getType().getMessage();
965 if (getCacheStrategy() == null){
966 logger.warn("No CacheStrategy defined for "+ typeName + ": " + this.getUuid());
967 return null;
968 }else{
969 if (getCacheStrategy() instanceof INomenclaturalReferenceCacheStrategy){
970 return cacheStrategy.getNomenclaturalCitation(this, microReference);
971 }else {
972 logger.warn("No INomenclaturalReferenceCacheStrategy defined for "+ typeName + ": " + this.getUuid());
973 return null;
974 }
975 }
976 }
977
978
979 /**
980 * Generates, according to the {@link eu.etaxonomy.cdm.strategy.strategy.cache.reference.IReferenceBaseCacheStrategy cache strategy}
981 * assigned to <i>this</i> reference, a string that identifies <i>this</i>
982 * reference and returns it. This string may be stored in the inherited
983 * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} attribute.<BR>
984 * This method overrides the generic and inherited generateTitle method
985 * from {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity IdentifiableEntity}.
986 *
987 * @return the string identifying <i>this</i> reference
988 * @see #getCitation()
989 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache()
990 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
991 * @see eu.etaxonomy.cdm.strategy.strategy.cache.common.IIdentifiableEntityCacheStrategy#getTitleCache()
992 */
993 // @Override
994 // public String generateTitle(){
995 // if (cacheStrategy == null){
996 // logger.warn("No CacheStrategy defined for Reference: " + this.getUuid());
997 // return null;
998 // }else{
999 // return cacheStrategy.getTitleCache(this);
1000 // }
1001 // }
1002
1003
1004
1005 //********** Casting methods ***********************************/
1006
1007 /**
1008 * @return
1009 */
1010 public IArticle castReferenceToArticle(){
1011 setType(ReferenceType.Article);
1012 return this;
1013 }
1014
1015 public IBook castReferenceToBook(){
1016 setType(ReferenceType.Book);
1017 return this;
1018 }
1019
1020 public IBookSection castReferenceToBookSection(){
1021 setType(ReferenceType.BookSection);
1022 return this;
1023 }
1024
1025 public ICdDvd castReferenceToCdDvd(){
1026 setType(ReferenceType.CdDvd);
1027 return this;
1028 }
1029
1030 public IDatabase castReferenceToDatabase(){
1031 setType(ReferenceType.Database);
1032 return this;
1033 }
1034
1035 public IGeneric castReferenceToGeneric(){
1036 setType(ReferenceType.Generic);
1037 return this;
1038 }
1039
1040 public IInProceedings castReferenceToInProceedings(){
1041 setType(ReferenceType.InProceedings);
1042 return this;
1043 }
1044
1045 public IJournal castReferenceToJournal(){
1046 setType(ReferenceType.Journal);
1047 return this;
1048 }
1049
1050 public IMap castReferenceToMap(){
1051 setType(ReferenceType.Map);
1052 return (IMap) this;
1053 }
1054
1055 public IPatent castReferenceToPatent(){
1056 setType(ReferenceType.Patent);
1057 return this;
1058 }
1059
1060 public IPersonalCommunication castReferenceToPersonalCommunication(){
1061 setType(ReferenceType.PersonalCommunication);
1062 return this;
1063 }
1064
1065 public IPrintSeries castReferenceToPrintSeries(){
1066 setType(ReferenceType.PrintSeries);
1067 return this;
1068 }
1069
1070 public IWebPage castReferenceToWebPage(){
1071 setType(ReferenceType.WebPage);
1072 return this;
1073 }
1074
1075 public IProceedings castReferenceToProceedings(){
1076 setType(ReferenceType.Proceedings);
1077 return this;
1078 }
1079
1080 public IReport castReferenceToReport(){
1081 setType(ReferenceType.Report);
1082 return this;
1083 }
1084
1085 public IThesis castReferenceToThesis(){
1086 setType(ReferenceType.Thesis);
1087 return this;
1088 }
1089
1090
1091 @Override
1092 @Transient // prevent from being serialized by webservice
1093 public IJournal getInJournal() {
1094 IJournal journal = this.inReference;
1095 return journal;
1096 }
1097
1098 @Override
1099 public void setInJournal(IJournal journal) {
1100 setInReference((Reference)journal); //user setter to invoke aspect #1815
1101 }
1102
1103 @Override
1104 @Transient // prevent from being serialized by webservice
1105 public IPrintSeries getInSeries() {
1106 return this.inReference;
1107 }
1108
1109 @Override
1110 public void setInSeries(IPrintSeries inSeries) {
1111 setInReference((Reference)inSeries); //user setter to invoke aspect #1815
1112 }
1113
1114 @Override
1115 @Transient // prevent from being serialized by webservice
1116 public IBook getInBook() {
1117 IBook book = this.inReference;
1118 return book;
1119 }
1120
1121 //********************** In-References *****************************************
1122
1123 @Override
1124 public void setInBook(IBook book) {
1125 setInReference((Reference)book); //user setter to invoke aspect #1815
1126 }
1127
1128 @Override
1129 @Transient // prevent from being serialized by webservice
1130 public IProceedings getInProceedings() {
1131 IProceedings proceedings = this.inReference;
1132 return proceedings;
1133 }
1134
1135 @Override
1136 public void setInProceedings(IProceedings proceeding) {
1137 setInReference((Reference)proceeding); //user setter to invoke aspect #1815
1138 }
1139
1140 //*************************** CACHE STRATEGIES ******************************/
1141
1142 @Override
1143 public INomenclaturalReferenceCacheStrategy getCacheStrategy() {
1144 return this.cacheStrategy;
1145 }
1146
1147 @Override
1148 public void setCacheStrategy(INomenclaturalReferenceCacheStrategy referenceCacheStrategy) {
1149 this.cacheStrategy = referenceCacheStrategy;
1150 }
1151
1152
1153
1154 //*********************** CLONE ********************************************************/
1155
1156 /**
1157 * Clones <i>this</i> reference. This is a shortcut that enables to create
1158 * a new instance that differs only slightly from <i>this</i> reference by
1159 * modifying only some of the attributes.
1160 *
1161 * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
1162 * @see java.lang.Object#clone()
1163 */
1164 @Override
1165 public Object clone() {
1166 try {
1167 Reference result = (Reference)super.clone();
1168 result.setDatePublished(datePublished != null? (TimePeriod)datePublished.clone(): null);
1169 //no changes to: title, authorship, hasProblem, nomenclaturallyRelevant, uri
1170 return result;
1171 } catch (CloneNotSupportedException e) {
1172 logger.warn("Object does not implement cloneable");
1173 e.printStackTrace();
1174 return null;
1175 }
1176 }
1177
1178 //******************************* toString *****************************/
1179
1180 @Override
1181 public String toString() {
1182 if (type != null){
1183 String result = "Reference [type=" + type + ", id= " + this.getId() + ", uuid=" + this.uuid ;
1184 result += title == null ? "" : ", title=" + title;
1185 result += abbrevTitle == null ? "" : ", abbrevTitle=" + abbrevTitle;
1186 result += "]";
1187 return result;
1188 }else{
1189 return super.toString();
1190 }
1191 }
1192
1193
1194
1195
1196 }
1197