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