Project

General

Profile

Download (36.4 KB) Statistics
| Branch: | Tag: | Revision:
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

    
(23-23/28)