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