Remove generics from Reference in cdmlib-model #5830
[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<IReferenceBaseCacheStrategy>
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 protected Reference inReference;
279
280 //********************************************************/
281
282 //The date range assigned to the reference. ISO Date range like. Flexible, year can be left out, etc
283 @XmlElement(name ="DatePublished" )
284 @Embedded
285 @IndexedEmbedded
286 private TimePeriod datePublished = TimePeriod.NewInstance();
287
288 @XmlElement(name ="Abstract" )
289 @Column(length=65536, name="referenceAbstract")
290 @Lob
291 @Field
292 //TODO Val #3379
293 // @NullOrNotEmpty
294 private String referenceAbstract; //abstract is a reserved term in Java
295
296
297 //URIs like DOIs, LSIDs or Handles for this reference
298 @XmlElement(name = "URI")
299 @Field(analyze = Analyze.NO)
300 @Type(type="uriUserType")
301 private URI uri;
302
303 //flag to subselect only references that could be useful for nomenclatural citations. If a reference is used as a
304 //nomenclatural reference in a name this flag should be automatically set
305 @XmlElement(name = "IsNomenclaturallyRelevant")
306 @Merge(MergeMode.OR)
307 private boolean nomenclaturallyRelevant;
308
309 @XmlElement(name = "Authorship")
310 @XmlIDREF
311 @XmlSchemaType(name = "IDREF")
312 @ManyToOne(fetch = FetchType.LAZY)
313 @IndexedEmbedded
314 @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
315 private TeamOrPersonBase<?> authorship;
316
317 @XmlAttribute
318 @Match(MatchMode.IGNORE)
319 private int parsingProblem = 0;
320
321 @XmlAttribute
322 @Match(MatchMode.IGNORE)
323 private int problemStarts = -1;
324
325 @XmlAttribute
326 @Match(MatchMode.IGNORE)
327 private int problemEnds = -1;
328
329 @Transient
330 @XmlAttribute
331 @Match(MatchMode.IGNORE)
332 private boolean cacheStrategyRectified = false;
333
334 protected Reference(){
335 this(ReferenceType.Generic); //just in case someone uses constructor
336 }
337
338 protected Reference(ReferenceType type) {
339 if (type == null){
340 this.type = ReferenceType.Generic;
341 } else{
342 this.type = type;
343 }
344 }
345
346 @Override
347 public void initListener(){
348 PropertyChangeListener listener = new PropertyChangeListener() {
349 @Override
350 public void propertyChange(PropertyChangeEvent ev) {
351 if (!ev.getPropertyName().equals("titleCache") && !ev.getPropertyName().equals("abbrevTitleCache") && !ev.getPropertyName().equals("cacheStrategy")){
352 if (! isProtectedTitleCache()){
353 titleCache = null;
354 }
355 if (! isProtectedAbbrevTitleCache()){
356 abbrevTitleCache = null;
357 }
358 }
359 }
360 };
361 addPropertyChangeListener(listener);
362 }
363
364
365 //*************************** GETTER / SETTER ******************************************/
366
367
368 @Override
369 public String getAbbrevTitleCache() {
370 if (protectedAbbrevTitleCache){
371 return this.abbrevTitleCache;
372 }
373 // is title dirty, i.e. equal NULL?
374 if (abbrevTitleCache == null){
375 this.abbrevTitleCache = generateAbbrevTitle();
376 this.abbrevTitleCache = getTruncatedCache(this.abbrevTitleCache) ;
377 }
378 return abbrevTitleCache;
379 }
380
381 @Override
382 @Deprecated
383 public void setAbbrevTitleCache(String abbrevTitleCache) {
384 this.abbrevTitleCache = abbrevTitleCache;
385 }
386
387 @Override
388 public void setAbbrevTitleCache(String abbrevTitleCache, boolean isProtected) {
389 this.protectedAbbrevTitleCache = isProtected;
390 setAbbrevTitleCache(abbrevTitleCache);
391 }
392
393 @Override
394 public boolean isProtectedAbbrevTitleCache() {
395 return protectedAbbrevTitleCache;
396 }
397
398 @Override
399 public void setProtectedAbbrevTitleCache(boolean protectedAbbrevTitleCache) {
400 this.protectedAbbrevTitleCache = protectedAbbrevTitleCache;
401 }
402
403 @Override
404 public String getAbbrevTitle() {
405 return abbrevTitle;
406 }
407
408 @Override
409 public void setAbbrevTitle(String abbrevTitle) {
410 this.abbrevTitle = StringUtils.isBlank(abbrevTitle) ? null : abbrevTitle;
411 }
412
413
414 @Override
415 public String getEditor() {
416 return editor;
417 }
418
419
420 @Override
421 public void setEditor(String editor) {
422 this.editor = StringUtils.isBlank(editor)? null : editor;
423 }
424
425 @Override
426 public String getVolume() {
427 return volume;
428 }
429
430 @Override
431 public void setVolume(String volume) {
432 this.volume = StringUtils.isBlank(volume)? null : volume;
433 }
434
435 @Override
436 public String getPages() {
437 return pages;
438 }
439
440 @Override
441 public void setPages(String pages) {
442 this.pages = StringUtils.isBlank(pages)? null : pages;
443 }
444
445 @Override
446 public String getEdition() {
447 return edition;
448 }
449
450 @Override
451 public void setEdition(String edition) {
452 this.edition = StringUtils.isBlank(edition)? null : edition;
453 }
454
455 @Override
456 public String getIsbn() {
457 return isbn;
458 }
459
460 @Override
461 public void setIsbn(String isbn) {
462 this.isbn = StringUtils.isBlank(isbn)? null : isbn;
463 }
464
465 @Override
466 public String getIssn() {
467 return issn;
468 }
469
470 @Override
471 public void setIssn(String issn) {
472 this.issn = StringUtils.isBlank(issn)? null : issn;
473 }
474
475 @Override
476 public DOI getDoi() {
477 return doi;
478 }
479
480 @Override
481 public void setDoi(DOI doi) {
482 this.doi = doi;
483 }
484
485 @Override
486 public String getSeriesPart() {
487 return seriesPart;
488 }
489
490 @Override
491 public void setSeriesPart(String seriesPart) {
492 this.seriesPart = StringUtils.isBlank(seriesPart)? null : seriesPart;
493 }
494
495 @Override
496 public String getOrganization() {
497 return organization;
498 }
499
500 @Override
501 public void setOrganization(String organization) {
502 this.organization = StringUtils.isBlank(organization)? null : organization;
503 }
504
505 @Override
506 public String getPublisher() {
507 return publisher;
508 }
509
510 @Override
511 public void setPublisher(String publisher) {
512 this.publisher = StringUtils.isBlank(publisher)? null : publisher;
513 }
514
515 @Override
516 public void setPublisher(String publisher, String placePublished){
517 this.publisher = publisher;
518 this.placePublished = placePublished;
519 }
520
521 @Override
522 public String getPlacePublished() {
523 return placePublished;
524 }
525
526 @Override
527 public void setPlacePublished(String placePublished) {
528 this.placePublished = StringUtils.isBlank(placePublished)? null: placePublished;
529 }
530
531 @Override
532 public Institution getInstitution() {
533 return institution;
534 }
535
536 @Override
537 public void setInstitution(Institution institution) {
538 this.institution = institution;
539 }
540
541 @Override
542 public Institution getSchool() {
543 return school;
544 }
545
546 @Override
547 public void setSchool(Institution school) {
548 this.school = school;
549 }
550
551 @Override
552 public Reference getInReference() {
553 return inReference;
554 }
555
556 @Override
557 public void setInReference(Reference inReference) {
558 this.inReference = inReference;
559 }
560
561 @Override
562 public void setType(ReferenceType type) {
563 if (type == null){
564 this.type = ReferenceType.Generic;
565 } else{
566 this.type = type;
567 }
568 this.setCacheStrategy(type.getCacheStrategy());
569
570 }
571
572 /**
573 * @return the type
574 */
575 @Override
576 public ReferenceType getType() {
577 return type;
578 }
579
580 /**
581 * Whether this reference is of the given type
582 *
583 * @param type
584 * @return
585 */
586 @Override
587 public boolean isOfType(ReferenceType type){
588 return type == getType();
589 }
590
591 /**
592 * Returns a string representing the title of <i>this</i> reference. If a
593 * reference has different titles (for instance abbreviated and not
594 * abbreviated) then for each title a new instance must be created.
595 *
596 * @return the title string of <i>this</i> reference
597 * @see #getCitation()
598 */
599 @Override
600 public String getTitle(){
601 return this.title;
602 }
603 /**
604 * @see #getTitle()
605 */
606 @Override
607 public void setTitle(String title){
608 this.title = StringUtils.isBlank(title)? null : title;
609 }
610
611 /**
612 * Returns the date (mostly only the year) of publication / creation of
613 * <i>this</i> reference.
614 */
615 @Override
616 public TimePeriod getDatePublished(){
617 return this.datePublished;
618 }
619 /**
620 * @see #getDatePublished()
621 */
622 @Override
623 public void setDatePublished(TimePeriod datePublished){
624 this.datePublished = datePublished;
625 }
626
627 public boolean hasDatePublished(){
628 boolean result = ! ( (this.datePublished == null) || StringUtils.isBlank(datePublished.toString()));
629 return result;
630 }
631
632 /**
633 * Returns the {@link eu.etaxonomy.cdm.model.agent.TeamOrPersonBase author (team)} who created the
634 * content of <i>this</i> reference.
635 *
636 * @return the author (team) of <i>this</i> reference
637 * @see eu.etaxonomy.cdm.model.agent.TeamOrPersonBase
638 */
639 @Override
640 public TeamOrPersonBase getAuthorship(){
641 return this.authorship;
642 }
643
644 /**
645 * @see #getAuthorship()
646 */
647 @Override
648 public void setAuthorship(TeamOrPersonBase authorship){
649 this.authorship = authorship;
650 }
651
652 /**
653 * Returns the Uniform Resource Identifier (URI) corresponding to <i>this</i>
654 * reference. An URI is a string of characters used to identify a resource
655 * on the Internet.
656 *
657 * @return the URI of <i>this</i> reference
658 */
659 @Override
660 public URI getUri(){
661 return this.uri;
662 }
663 /**
664 * @see #getUri()
665 */
666 @Override
667 public void setUri(URI uri){
668 this.uri = uri;
669 }
670
671 /**
672 * @return the referenceAbstract
673 */
674 @Override
675 public String getReferenceAbstract() {
676 return referenceAbstract;
677 }
678
679 /**
680 * @param referenceAbstract the referenceAbstract to set
681 */
682 @Override
683 public void setReferenceAbstract(String referenceAbstract) {
684 this.referenceAbstract = StringUtils.isBlank(referenceAbstract)? null : referenceAbstract;
685 }
686
687
688 /**
689 * Returns "true" if the isNomenclaturallyRelevant flag is set. This
690 * indicates that a {@link TaxonNameBase taxon name} has been originally
691 * published in <i>this</i> reference following the rules of a
692 * {@link eu.etaxonomy.cdm.model.name.NomenclaturalCode nomenclature code} and is therefore used for
693 * nomenclatural citations. This flag will be set as soon as <i>this</i>
694 * reference is used as a nomenclatural reference for any taxon name.<BR>
695 * FIXME what happens if the only taxon name referencing this reference is not
696 * any longer using this reference as a nomenclatural reference. How does the
697 * reference get informed about the fact that it is not nomenclaturally relevant
698 * anymore?
699 */
700 public boolean isNomenclaturallyRelevant(){
701 return this.nomenclaturallyRelevant;
702 }
703
704 /**
705 * @see #isNomenclaturallyRelevant()
706 */
707 public void setNomenclaturallyRelevant(boolean nomenclaturallyRelevant){
708 this.nomenclaturallyRelevant = nomenclaturallyRelevant;
709 }
710
711
712 //**************************************************** /
713
714
715 /**
716 * Returns a formatted string containing the entire reference citation,
717 * including authors, corresponding to <i>this</i> reference.
718 *
719 * @see #generateTitle()
720 */
721 // TODO implement
722 @Transient
723 public String getCitation(){
724 rectifyCacheStrategy();
725 if (getCacheStrategy() == null){
726 logger.warn("No CacheStrategy defined for "+ this.getClass() + ": " + this.getUuid());
727 return null;
728 }else{
729 return getCacheStrategy().getTitleCache(this);
730 }
731 }
732
733
734 @Override
735 public String generateTitle() {
736 rectifyCacheStrategy();
737 return super.generateTitle();
738 }
739
740 public String generateAbbrevTitle() {
741 rectifyCacheStrategy(); //TODO needed, is called by getCacheStrategy already
742 return getCacheStrategy().getAbbrevTitleCache(this);
743 }
744
745 /**
746 * Returns a string representation for the year of publication / creation
747 * of <i>this</i> reference. If the {@link #getDatePublished() datePublished}
748 * of this reference contains more date information then (starting) year
749 * only the year is returned.
750 * than attribute.
751 */
752 @Override
753 @Transient
754 public String getYear(){
755 TimePeriod datePublished = this.getDatePublished();
756 if (datePublished != null ){
757 String result = getDatePublished().getYear();
758 return result;
759 }else{
760 return null;
761 }
762 }
763
764 /**
765 * Convenience method that returns a string representation for the publication date / creation
766 * of <i>this</i> reference. The string is obtained by
767 * {@link #getDatePublished()#toString() the string representation
768 * of the date published}.
769 */
770 @Transient
771 public String getDatePublishedString(){
772 TimePeriod datePublished = this.getDatePublished();
773 if (datePublished != null ){
774 return getDatePublished().toString();
775 }else{
776 return null;
777 }
778 }
779
780
781 @Override
782 public int getParsingProblem(){
783 return this.parsingProblem;
784 }
785
786 @Override
787 public void setParsingProblem(int parsingProblem){
788 this.parsingProblem = parsingProblem;
789 }
790
791 @Override
792 public boolean hasProblem(){
793 return parsingProblem != 0;
794 }
795
796 @Override
797 public boolean hasProblem(ParserProblem problem) {
798 return getParsingProblems().contains(problem);
799 }
800
801 @Override
802 public int getProblemStarts(){
803 return this.problemStarts;
804 }
805
806 @Override
807 public void setProblemStarts(int start) {
808 this.problemStarts = start;
809 }
810
811 @Override
812 public int getProblemEnds(){
813 return this.problemEnds;
814 }
815
816 @Override
817 public void setProblemEnds(int end) {
818 this.problemEnds = end;
819 }
820
821 @Override
822 public void addParsingProblem(ParserProblem warning){
823 parsingProblem = ParserProblem.addProblem(parsingProblem, warning);
824 }
825
826 @Override
827 public void removeParsingProblem(ParserProblem problem) {
828 parsingProblem = ParserProblem.removeProblem(parsingProblem, problem);
829 }
830
831 @Override
832 @Transient
833 public List<ParserProblem> getParsingProblems() {
834 return ParserProblem.warningList(this.parsingProblem);
835 }
836
837
838 @Override
839 @Transient
840 public String getNomenclaturalCitation(String microReference) {
841 rectifyCacheStrategy();
842 String typeName = this.getType()== null ? "(no type defined)" : this.getType().getMessage();
843 if (getCacheStrategy() == null){
844 logger.warn("No CacheStrategy defined for "+ typeName + ": " + this.getUuid());
845 return null;
846 }else{
847 if (getCacheStrategy() instanceof INomenclaturalReferenceCacheStrategy){
848 return ((INomenclaturalReferenceCacheStrategy)cacheStrategy).getNomenclaturalCitation(this, microReference);
849 }else {
850 logger.warn("No INomenclaturalReferenceCacheStrategy defined for "+ typeName + ": " + this.getUuid());
851 return null;
852 }
853 }
854 }
855
856
857 /**
858 * Generates, according to the {@link eu.etaxonomy.cdm.strategy.strategy.cache.reference.IReferenceBaseCacheStrategy cache strategy}
859 * assigned to <i>this</i> reference, a string that identifies <i>this</i>
860 * reference and returns it. This string may be stored in the inherited
861 * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} attribute.<BR>
862 * This method overrides the generic and inherited generateTitle method
863 * from {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity IdentifiableEntity}.
864 *
865 * @return the string identifying <i>this</i> reference
866 * @see #getCitation()
867 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache()
868 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
869 * @see eu.etaxonomy.cdm.strategy.strategy.cache.common.IIdentifiableEntityCacheStrategy#getTitleCache()
870 */
871 // @Override
872 // public String generateTitle(){
873 // if (cacheStrategy == null){
874 // logger.warn("No CacheStrategy defined for Reference: " + this.getUuid());
875 // return null;
876 // }else{
877 // return cacheStrategy.getTitleCache(this);
878 // }
879 // }
880
881
882
883 //********** Casting methods ***********************************/
884
885 /**
886 * @return
887 */
888 public IArticle castReferenceToArticle(){
889 setType(ReferenceType.Article);
890 return this;
891 }
892
893 public IBook castReferenceToBook(){
894 setType(ReferenceType.Book);
895 return this;
896 }
897
898 public IBookSection castReferenceToBookSection(){
899 setType(ReferenceType.BookSection);
900 return this;
901 }
902
903 public ICdDvd castReferenceToCdDvd(){
904 setType(ReferenceType.CdDvd);
905 return this;
906 }
907
908 public IDatabase castReferenceToDatabase(){
909 setType(ReferenceType.Database);
910 return this;
911 }
912
913 public IGeneric castReferenceToGeneric(){
914 setType(ReferenceType.Generic);
915 return this;
916 }
917
918 public IInProceedings castReferenceToInProceedings(){
919 setType(ReferenceType.InProceedings);
920 return this;
921 }
922
923 public IJournal castReferenceToJournal(){
924 setType(ReferenceType.Journal);
925 return this;
926 }
927
928 public IMap castReferenceToMap(){
929 setType(ReferenceType.Map);
930 return (IMap) this;
931 }
932
933 public IPatent castReferenceToPatent(){
934 setType(ReferenceType.Patent);
935 return this;
936 }
937
938 public IPersonalCommunication castReferenceToPersonalCommunication(){
939 setType(ReferenceType.PersonalCommunication);
940 return this;
941 }
942
943 public IPrintSeries castReferenceToPrintSeries(){
944 setType(ReferenceType.PrintSeries);
945 return this;
946 }
947
948 public IWebPage castReferenceToWebPage(){
949 setType(ReferenceType.WebPage);
950 return this;
951 }
952
953 public IProceedings castReferenceToProceedings(){
954 setType(ReferenceType.Proceedings);
955 return this;
956 }
957
958 public IReport castReferenceToReport(){
959 setType(ReferenceType.Report);
960 return this;
961 }
962
963 public IThesis castReferenceToThesis(){
964 setType(ReferenceType.Thesis);
965 return this;
966 }
967
968
969 @Override
970 @Transient // prevent from being serialized by webservice
971 public IJournal getInJournal() {
972 IJournal journal = this.inReference;
973 return journal;
974 }
975
976 @Override
977 public void setInJournal(IJournal journal) {
978 this.inReference = (Reference)journal;
979
980 }
981
982 @Override
983 @Transient // prevent from being serialized by webservice
984 public IPrintSeries getInSeries() {
985 IPrintSeries printSeries = this.inReference;
986 return printSeries;
987 }
988
989 @Override
990 public void setInSeries(IPrintSeries inSeries) {
991 this.inReference = (Reference) inSeries;
992 }
993
994 @Override
995 @Transient // prevent from being serialized by webservice
996 public IBook getInBook() {
997 IBook book = this.inReference;
998 return book;
999 }
1000
1001 //********************** In-References *****************************************
1002
1003 @Override
1004 public void setInBook(IBook book) {
1005 this.inReference = (Reference) book;
1006 }
1007
1008 @Override
1009 @Transient // prevent from being serialized by webservice
1010 public IProceedings getInProceedings() {
1011 IProceedings proceedings = this.inReference;
1012 return proceedings;
1013 }
1014
1015 @Override
1016 public void setInProceedings(IProceedings proceeding) {
1017 this.inReference = (Reference) proceeding;
1018 }
1019
1020 //*************************** CACHE STRATEGIES ******************************/
1021
1022 @Override
1023 public IReferenceBaseCacheStrategy getCacheStrategy() {
1024 rectifyCacheStrategy();
1025 return this.cacheStrategy;
1026 }
1027
1028 /**
1029 * The type property of this class is mapped on the field level to the data base column, so
1030 * Hibernate will consequently use the {@link org.hibernate.property.DirectPropertyAccessor}
1031 * to set the property. This PropertyAccessor directly sets the field instead of using the according setter so
1032 * the CacheStrategy is not correctly set after the initialization of the bean. Thus we need to
1033 * validate the CacheStrategy before it is to be used.
1034 */
1035 private void rectifyCacheStrategy() {
1036 if(!cacheStrategyRectified ){
1037 setType(getType());
1038 cacheStrategyRectified = true;
1039 }
1040 }
1041
1042
1043 @Override
1044 public void setCacheStrategy(IReferenceBaseCacheStrategy iReferenceBaseCacheStrategy) {
1045 this.cacheStrategy = iReferenceBaseCacheStrategy;
1046
1047 }
1048
1049 @Override
1050 public void setCacheStrategy(ArticleDefaultCacheStrategy cacheStrategy) {
1051 this.cacheStrategy = cacheStrategy;
1052 }
1053
1054 @Override
1055 public void setCacheStrategy(BookDefaultCacheStrategy cacheStrategy) {
1056 this.cacheStrategy = cacheStrategy;
1057 }
1058
1059 @Override
1060 public void setCacheStrategy(JournalDefaultCacheStrategy cacheStrategy) {
1061 this.cacheStrategy = cacheStrategy;
1062 }
1063
1064 @Override
1065 public void setCacheStrategy(BookSectionDefaultCacheStrategy cacheStrategy) {
1066 this.cacheStrategy = cacheStrategy;
1067 }
1068
1069 @Override
1070 public void setCacheStrategy(GenericDefaultCacheStrategy cacheStrategy) {
1071 this.cacheStrategy = cacheStrategy;
1072 }
1073
1074 public void setCacheStrategy(ReferenceDefaultCacheStrategy cacheStrategy) {
1075 this.cacheStrategy = cacheStrategy;
1076
1077 }
1078
1079
1080
1081 // @Override
1082 // protected void initListener(){
1083 // PropertyChangeListener listener = new PropertyChangeListener() {
1084 // @Override
1085 // public void propertyChange(PropertyChangeEvent e) {
1086 // boolean protectedByLowerCache = false;
1087 // //authorship cache
1088 // if (fieldHasCacheUpdateProperty(e.getPropertyName(), "authorshipCache")){
1089 // if (protectedAuthorshipCache){
1090 // protectedByLowerCache = true;
1091 // }else{
1092 // authorshipCache = null;
1093 // }
1094 // }
1095 //
1096 // //title cache
1097 // if (! fieldHasNoUpdateProperty(e.getPropertyName(), "titleCache")){
1098 // if (isProtectedTitleCache()|| protectedByLowerCache == true ){
1099 // protectedByLowerCache = true;
1100 // }else{
1101 // titleCache = null;
1102 // }
1103 // }
1104 // //full title cache
1105 // if (! fieldHasNoUpdateProperty(e.getPropertyName(), "fullTitleCache")){
1106 // if (isProtectedFullTitleCache()|| protectedByLowerCache == true ){
1107 // protectedByLowerCache = true;
1108 // }else{
1109 // fullTitleCache = null;
1110 // }
1111 // }
1112 // }
1113 // };
1114 // addPropertyChangeListener(listener); //didn't use this.addXXX to make lsid.AssemblerTest run in cdmlib-remote
1115 // }
1116
1117
1118 //*********************** CLONE ********************************************************/
1119
1120 /**
1121 * Clones <i>this</i> reference. This is a shortcut that enables to create
1122 * a new instance that differs only slightly from <i>this</i> reference by
1123 * modifying only some of the attributes.
1124 *
1125 * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
1126 * @see java.lang.Object#clone()
1127 */
1128 @Override
1129 public Object clone() {
1130 try {
1131 Reference result = (Reference)super.clone();
1132 result.setDatePublished(datePublished != null? (TimePeriod)datePublished.clone(): null);
1133 //no changes to: title, authorship, hasProblem, nomenclaturallyRelevant, uri
1134 return result;
1135 } catch (CloneNotSupportedException e) {
1136 logger.warn("Object does not implement cloneable");
1137 e.printStackTrace();
1138 return null;
1139 }
1140 }
1141
1142 //******************************* toString *****************************/
1143
1144 @Override
1145 public String toString() {
1146 if (type != null){
1147 String result = "Reference [type=" + type + ", id= " + this.getId() + ", uuid=" + this.uuid ;
1148 result += title == null ? "" : ", title=" + title;
1149 result += abbrevTitle == null ? "" : ", abbrevTitle=" + abbrevTitle;
1150 result += "]";
1151 return result;
1152 }else{
1153 return super.toString();
1154 }
1155 }
1156
1157
1158
1159
1160 }
1161