Project

General

Profile

Download (31.5 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.Basic;
18
import javax.persistence.Column;
19
import javax.persistence.Embedded;
20
import javax.persistence.Entity;
21
import javax.persistence.FetchType;
22
import javax.persistence.Inheritance;
23
import javax.persistence.InheritanceType;
24
import javax.persistence.Lob;
25
import javax.persistence.ManyToOne;
26
import javax.persistence.Transient;
27
import javax.validation.constraints.NotNull;
28
import javax.validation.constraints.Pattern;
29
import javax.xml.bind.annotation.XmlAccessType;
30
import javax.xml.bind.annotation.XmlAccessorType;
31
import javax.xml.bind.annotation.XmlAttribute;
32
import javax.xml.bind.annotation.XmlElement;
33
import javax.xml.bind.annotation.XmlIDREF;
34
import javax.xml.bind.annotation.XmlRootElement;
35
import javax.xml.bind.annotation.XmlSchemaType;
36
import javax.xml.bind.annotation.XmlTransient;
37
import javax.xml.bind.annotation.XmlType;
38
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
39

    
40
import org.apache.commons.lang.StringUtils;
41
import org.apache.log4j.Logger;
42
import org.hibernate.annotations.Cascade;
43
import org.hibernate.annotations.CascadeType;
44
import org.hibernate.annotations.Table;
45
import org.hibernate.annotations.Type;
46
import org.hibernate.envers.Audited;
47
import org.hibernate.search.annotations.Analyze;
48
import org.hibernate.search.annotations.Field;
49
import org.hibernate.search.annotations.FieldBridge;
50
import org.hibernate.search.annotations.IndexedEmbedded;
51
import org.joda.time.DateTime;
52

    
53
import eu.etaxonomy.cdm.common.DOI;
54
import eu.etaxonomy.cdm.hibernate.search.DateTimeBridge;
55
import eu.etaxonomy.cdm.hibernate.search.DoiBridge;
56
import eu.etaxonomy.cdm.jaxb.DateTimeAdapter;
57
import eu.etaxonomy.cdm.model.agent.Institution;
58
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
59
import eu.etaxonomy.cdm.model.common.IIntextReferenceTarget;
60
import eu.etaxonomy.cdm.model.common.TimePeriod;
61
import eu.etaxonomy.cdm.model.common.VerbatimTimePeriod;
62
import eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity;
63
import eu.etaxonomy.cdm.model.name.TaxonName;
64
import eu.etaxonomy.cdm.strategy.cache.reference.DefaultReferenceCacheStrategy;
65
import eu.etaxonomy.cdm.strategy.cache.reference.INomenclaturalReferenceCacheStrategy;
66
import eu.etaxonomy.cdm.strategy.match.Match;
67
import eu.etaxonomy.cdm.strategy.match.MatchMode;
68
import eu.etaxonomy.cdm.strategy.merge.Merge;
69
import eu.etaxonomy.cdm.strategy.merge.MergeMode;
70
import eu.etaxonomy.cdm.strategy.parser.ParserProblem;
71
import eu.etaxonomy.cdm.validation.Level2;
72
import eu.etaxonomy.cdm.validation.Level3;
73
import eu.etaxonomy.cdm.validation.annotation.InReference;
74
import eu.etaxonomy.cdm.validation.annotation.NoRecursiveInReference;
75
import eu.etaxonomy.cdm.validation.annotation.NullOrNotEmpty;
76
import eu.etaxonomy.cdm.validation.annotation.ReferenceCheck;
77

    
78
/**
79
 * The class for references (information sources). Originally
80
 * an abstract class with many subclasses. Not it is only
81
 * one class implementing many interfaces for safe use.
82
 * <P>
83
 * This class corresponds to: <ul>
84
 * <li> PublicationCitation according to the TDWG ontology
85
 * <li> Publication according to the TCS
86
 * <li> Reference according to the ABCD schema
87
 * </ul>
88
 *
89
 * @author m.doering
90
 * @since 08-Nov-2007 13:06:47
91
 */
92
@XmlAccessorType(XmlAccessType.FIELD)
93
@XmlType(name = "Reference", propOrder = {
94
	"type",
95
	"uri",
96
    "abbrevTitleCache",
97
    "protectedAbbrevTitleCache",
98
	"nomenclaturallyRelevant",
99
    "authorship",
100
    "referenceAbstract",
101
    "title",
102
    "abbrevTitle",
103
    "editor",
104
	"volume",
105
	"pages",
106
	"edition",
107
    "isbn",
108
    "issn",
109
    "doi",
110
    "seriesPart",
111
    "datePublished",
112
    "publisher",
113
    "placePublished",
114
    "institution",
115
    "school",
116
    "organization",
117
    "inReference",
118
    "accessed",
119
    "lastRetrieved",
120
    "externalId",
121
    "externalLink",
122
    "authorityType"
123
})
124
@XmlRootElement(name = "Reference")
125
@Entity
126
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
127
@Audited
128
@Table(appliesTo="Reference", indexes = { @org.hibernate.annotations.Index(name = "ReferenceTitleCacheIndex", columnNames = { "titleCache" }) })
129
//@InReference(groups=Level3.class)
130
@ReferenceCheck(groups=Level2.class)
131
@InReference(groups=Level3.class)
132
@NoRecursiveInReference(groups=Level3.class)  //may become Level1 in future  #
133
public class Reference
134
        extends IdentifiableMediaEntity<INomenclaturalReferenceCacheStrategy>
135
        implements IArticle, IBook, IPatent, IDatabase, IJournal, IBookSection,ICdDvd,
136
                   IGeneric,IInProceedings, IProceedings, IPrintSeries, IReport,
137
                   IThesis,IWebPage, IPersonalCommunication,
138
                   INomenclaturalReference, IReference, IIntextReferenceTarget,
139
                   Cloneable {
140

    
141
    private static final long serialVersionUID = -2034764545042691295L;
142
	private static final Logger logger = Logger.getLogger(Reference.class);
143

    
144
	@XmlAttribute(name ="type")
145
	@Column(name="refType")
146
	@NotNull
147
    @Type(type = "eu.etaxonomy.cdm.hibernate.EnumUserType",
148
    	parameters = {@org.hibernate.annotations.Parameter(name  = "enumClass", value = "eu.etaxonomy.cdm.model.reference.ReferenceType")}
149
    )
150
	@Audited
151
	protected ReferenceType type;
152

    
153
	//Title of the reference
154
	@XmlElement(name ="Title" )
155
	@Column(length=4096, name="title")
156
	@Lob
157
	@Field
158
	@Match(MatchMode.EQUAL_REQUIRED) //TODO correct? was EQUAL_REQUIRED before, but with abbrevTitle this is not realistic anymore
159
    //TODO Val #3379
160
//	@NullOrNotEmpty
161
	private String title;
162

    
163
	//Title of the reference
164
	@XmlElement(name ="AbbrevTitle" )
165
	@Field
166
	@Match(MatchMode.EQUAL)  //TODO check if this is correct
167
	@NullOrNotEmpty
168
	@Column(length=255)
169
	private String abbrevTitle;
170

    
171
	//Title of the reference
172
	@XmlElement(name ="AbbrevTitleCache" )
173
	@Field
174
	@Match(MatchMode.CACHE)
175
    //TODO Val #3379
176
//	@NotNull
177
	@Column(length=1024)
178
	private String abbrevTitleCache;
179

    
180
	@XmlElement(name = "protectedAbbrevTitleCache")
181
	@Merge(MergeMode.OR)
182
	private boolean protectedAbbrevTitleCache;
183

    
184
//********************************************************/
185

    
186

    
187
    @XmlElement(name = "Editor")
188
    @Field
189
    //TODO Val #3379
190
//    @NullOrNotEmpty
191
    @Column(length=255)
192
	protected String editor;
193

    
194
    @XmlElement(name = "Volume")
195
    @Field
196
    //TODO Val #3379
197
//    @NullOrNotEmpty
198
    @Column(length=255)
199
	protected String volume;
200

    
201
    @XmlElement(name = "Pages")
202
    @Field
203
    //TODO Val #3379
204
//    @NullOrNotEmpty
205
    @Column(length=255)
206
	protected String pages;
207

    
208
    @XmlElement(name = "Edition")
209
    @Field
210
    //TODO Val #3379
211
//    @NullOrNotEmpty
212
    @Column(length=255)
213
	protected String edition;
214

    
215
    @XmlElement(name = "ISBN")
216
    @Field
217
    //TODO Val #3379
218
//    @NullOrNotEmpty
219
    @Column(length=255)
220
	@Pattern(regexp = "(?=.{13}$)\\d{1,5}([- ])\\d{1,7}\\1\\d{1,6}\\1(\\d|X)$", groups = Level2.class, message = "{eu.etaxonomy.cdm.model.reference.Reference.isbn.message}")
221
	protected String isbn;
222

    
223
    @XmlElement(name = "Doi")
224
    @Field
225
    @FieldBridge(impl = DoiBridge.class)
226
    @Type(type="doiUserType")
227
    @Column(length=DOI.MAX_LENGTH)
228
    protected DOI doi;
229

    
230

    
231
	@XmlElement(name = "ISSN")
232
    @Field
233
    //TODO Val #3379
234
//	@NullOrNotEmpty
235
    @Column(length=255)
236
	@Pattern(regexp = "(?=.{9}$)\\d{4}([- ])\\d{4} (\\d|X)$", groups = Level2.class, message = "{eu.etaxonomy.cdm.model.reference.Reference.issn.message}")
237
	protected String issn;
238

    
239
    @XmlElement(name = "SeriesPart")
240
    @Field
241
    //TODO Val #3379
242
//    @NullOrNotEmpty
243
    @Column(length=255)
244
	protected String seriesPart;
245

    
246
	@XmlElement(name = "Organization")
247
    @Field
248
    //TODO Val #3379
249
//	@NullOrNotEmpty
250
    @Column(length=255)
251
	protected String organization;
252

    
253
	@XmlElement(name = "Publisher")
254
    @Field
255
    //TODO Val #3379
256
//	@NullOrNotEmpty
257
    @Column(length=255)
258
	protected String publisher;
259

    
260

    
261
	@XmlElement(name = "PlacePublished")
262
    @Field
263
    //TODO Val #3379
264
//	@NullOrNotEmpty
265
    @Column(length=255)
266
	protected String placePublished;
267

    
268
	@XmlElement(name = "Institution")
269
	@XmlIDREF
270
	@XmlSchemaType(name = "IDREF")
271
	@ManyToOne(fetch = FetchType.LAZY)
272
	@IndexedEmbedded
273
	@Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
274
	protected Institution institution;
275

    
276
	@XmlElement(name = "School")
277
    @XmlIDREF
278
    @XmlSchemaType(name = "IDREF")
279
	@ManyToOne(fetch = FetchType.LAZY)
280
	@IndexedEmbedded
281
	@Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
282
	protected Institution school;
283

    
284
    @XmlElement(name = "InReference")
285
    @XmlIDREF
286
    @XmlSchemaType(name = "IDREF")
287
    @ManyToOne(fetch = FetchType.LAZY)
288
//  @IndexedEmbedded
289
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
290
//  @InReference(groups=Level2.class)
291
   	protected Reference inReference;
292

    
293
//********************************************************/
294

    
295
	//The date range assigned to the reference. ISO Date range like. Flexible, year can be left out, etc
296
	@XmlElement(name ="DatePublished" )
297
	@Embedded
298
	@IndexedEmbedded
299
	private VerbatimTimePeriod datePublished = VerbatimTimePeriod.NewVerbatimInstance();
300

    
301
    //#5258
302
    @XmlElement (name = "Accessed", type= String.class)
303
    @XmlJavaTypeAdapter(DateTimeAdapter.class)
304
    @Type(type="dateTimeUserType")
305
    @Basic(fetch = FetchType.LAZY)
306
    @Match(MatchMode.EQUAL)
307
    @FieldBridge(impl = DateTimeBridge.class)
308
    private DateTime accessed;
309

    
310
    @XmlElement(name ="Abstract" )
311
	@Column(length=65536, name="referenceAbstract")
312
	@Lob
313
    @Field
314
    //TODO Val #3379
315
//	@NullOrNotEmpty
316
	private String referenceAbstract;  //abstract is a reserved term in Java
317

    
318

    
319
	//URIs like DOIs, LSIDs or Handles for this reference
320
	@XmlElement(name = "URI")
321
	@Field(analyze = Analyze.NO)
322
	@Type(type="uriUserType")
323
	private URI uri;
324

    
325
	//flag to subselect only references that could be useful for nomenclatural citations.
326
	//If a reference is used as a
327
	//nomenclatural reference in a name this flag should be automatically set
328
	@XmlElement(name = "IsNomenclaturallyRelevant")
329
	@Merge(MergeMode.OR)
330
	private boolean nomenclaturallyRelevant;
331

    
332
	@XmlElement(name = "Authorship")
333
	@XmlIDREF
334
	@XmlSchemaType(name = "IDREF")
335
	@ManyToOne(fetch = FetchType.LAZY)
336
	@IndexedEmbedded
337
	@Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
338
	private TeamOrPersonBase<?> authorship;
339

    
340
	@XmlAttribute
341
    @Match(MatchMode.IGNORE)
342
	private int parsingProblem = 0;
343

    
344
	@XmlAttribute
345
    @Match(MatchMode.IGNORE)
346
    private int problemStarts = -1;
347

    
348
    @XmlAttribute
349
    @Match(MatchMode.IGNORE)
350
    private int problemEnds = -1;
351

    
352
    @Transient
353
    @XmlAttribute
354
    @Match(MatchMode.IGNORE)
355
	private boolean cacheStrategyRectified = false;
356

    
357
    //attributes for externally managed
358

    
359
//    @XmlElement (name = "LastRetrieved", type= String.class)
360
    @XmlJavaTypeAdapter(DateTimeAdapter.class)
361
    @Type(type="dateTimeUserType")
362
    //TODO needed??
363
    @Basic(fetch = FetchType.LAZY)
364
    private DateTime lastRetrieved;
365

    
366
    @XmlElement(name ="ExternalId" )
367
//    @Field
368
//    @Match(MatchMode.EQUAL)  //TODO check if this is correct
369
    @NullOrNotEmpty
370
    @Column(length=255)
371
    private String externalId;
372

    
373
    //Actionable link on e.g. on a webservice
374
    @XmlElement(name = "ExternalLink")
375
    @Field(analyze = Analyze.NO)
376
    @Type(type="uriUserType")
377
    private URI externalLink;
378

    
379
    @XmlAttribute(name ="authority")
380
    @Column(name="authorityType", length=10)
381
    @Type(type = "eu.etaxonomy.cdm.hibernate.EnumUserType",
382
        parameters = {@org.hibernate.annotations.Parameter(name  = "enumClass", value = "eu.etaxonomy.cdm.model.reference.AuthorityType")}
383
    )
384
//    @NotNull
385
    private AuthorityType authorityType;
386

    
387
// *********************** CONSTRUCTOR ************************/
388

    
389
    protected Reference(){
390
		this(ReferenceType.Generic);  //just in case someone uses constructor
391
	}
392

    
393
	protected Reference(ReferenceType type) {
394
		super();
395
	    if (type == null){
396
			this.type = ReferenceType.Generic;
397
		} else{
398
			this.type = type;
399
		}
400
		this.setCacheStrategy(DefaultReferenceCacheStrategy.NewInstance());
401
	}
402

    
403
// *********************** LISTENER ************************/
404

    
405

    
406
	@Override
407
    public void initListener(){
408
        PropertyChangeListener listener = new PropertyChangeListener() {
409
            @Override
410
            public void propertyChange(PropertyChangeEvent ev) {
411
            	if (!ev.getPropertyName().equals("titleCache") && !ev.getPropertyName().equals("abbrevTitleCache") && !ev.getPropertyName().equals("cacheStrategy")){
412
            		if (! isProtectedTitleCache()){
413
            			titleCache = null;
414
            		}
415
            		if (! isProtectedAbbrevTitleCache()){
416
            			abbrevTitleCache = null;
417
            		}
418
            	}
419
            }
420
        };
421
        addPropertyChangeListener(listener);
422
    }
423

    
424

    
425
//*************************** GETTER / SETTER ******************************************/
426

    
427

    
428

    
429
    // @Transient  - must not be transient, since this property needs to to be included in all serializations produced by the remote layer
430
    @Override
431
    public String getTitleCache(){
432
        String result = super.getTitleCache();
433
        if (isBlank(result)){
434
            this.titleCache = this.getAbbrevTitleCache(true);
435
        }
436
        return titleCache;
437
    }
438

    
439
	@Override
440
	public String getAbbrevTitleCache() {
441
		return getAbbrevTitleCache(false);
442
	}
443

    
444
	/**
445
	 * Implements {@link #getAbbrevTitleCache()} but allows to
446
	 * avoid never ending recursions if both caches are empty
447
	 * avoidRecursion should only be <code>true</code> if called
448
	 * by {@link #getTitleCache()}
449
	 * @param avoidRecursion
450
	 * @return
451
	 */
452
	private String getAbbrevTitleCache(boolean avoidRecursion) {
453
        if (protectedAbbrevTitleCache){
454
            return this.abbrevTitleCache;
455
        }
456
        // is reference dirty, i.e. equal NULL?
457
        if (abbrevTitleCache == null){
458
            this.abbrevTitleCache = generateAbbrevTitle();
459
            this.abbrevTitleCache = getTruncatedCache(this.abbrevTitleCache) ;
460
        }
461
        if (isBlank(abbrevTitleCache) && !avoidRecursion){
462
            this.abbrevTitleCache = this.getTitleCache();
463
        }
464
        return abbrevTitleCache;
465
    }
466

    
467

    
468
    @Override
469
	@Deprecated
470
	public void setAbbrevTitleCache(String abbrevTitleCache) {
471
		this.abbrevTitleCache = abbrevTitleCache;
472
	}
473

    
474
	@Override
475
	public void setAbbrevTitleCache(String abbrevTitleCache, boolean isProtected) {
476
		this.protectedAbbrevTitleCache = isProtected;
477
		setAbbrevTitleCache(abbrevTitleCache);
478
	}
479

    
480
	@Override
481
	public boolean isProtectedAbbrevTitleCache() {
482
		return protectedAbbrevTitleCache;
483
	}
484

    
485
	@Override
486
	public void setProtectedAbbrevTitleCache(boolean protectedAbbrevTitleCache) {
487
		this.protectedAbbrevTitleCache = protectedAbbrevTitleCache;
488
	}
489

    
490
	@Override
491
	public String getAbbrevTitle() {
492
		return abbrevTitle;
493
	}
494

    
495
	@Override
496
	public void setAbbrevTitle(String abbrevTitle) {
497
		this.abbrevTitle = StringUtils.isBlank(abbrevTitle) ? null : abbrevTitle;
498
	}
499

    
500

    
501
	@Override
502
    public String getEditor() {
503
		return editor;
504
	}
505

    
506

    
507
	@Override
508
    public void setEditor(String editor) {
509
		this.editor = StringUtils.isBlank(editor)? null : editor;
510
	}
511

    
512
	@Override
513
    public String getVolume() {
514
		return volume;
515
	}
516

    
517
	@Override
518
    public void setVolume(String volume) {
519
		this.volume = StringUtils.isBlank(volume)? null : volume;
520
	}
521

    
522
	@Override
523
    public String getPages() {
524
		return pages;
525
	}
526

    
527
	@Override
528
    public void setPages(String pages) {
529
		this.pages = StringUtils.isBlank(pages)? null : pages;
530
	}
531

    
532
	@Override
533
    public String getEdition() {
534
		return edition;
535
	}
536

    
537
	@Override
538
    public void setEdition(String edition) {
539
		this.edition = StringUtils.isBlank(edition)? null : edition;
540
	}
541

    
542
	@Override
543
    public String getIsbn() {
544
		return isbn;
545
	}
546

    
547
	@Override
548
    public void setIsbn(String isbn) {
549
		this.isbn = StringUtils.isBlank(isbn)? null : isbn;
550
	}
551

    
552
	@Override
553
    public String getIssn() {
554
		return issn;
555
	}
556

    
557
	@Override
558
    public void setIssn(String issn) {
559
		this.issn = StringUtils.isBlank(issn)? null : issn;
560
	}
561

    
562
    @Override
563
	public DOI getDoi() {
564
		return doi;
565
	}
566
    @Override
567
	public void setDoi(DOI doi) {
568
		this.doi = doi;
569
	}
570
    /**
571
     * Convenience method to retrieve doi as string
572
     */
573
    @Transient @XmlTransient @java.beans.Transient
574
    public String getDoiString() {
575
        return doi == null? null : doi.toString();
576
    }
577

    
578
	@Override
579
    public String getSeriesPart() {
580
		return seriesPart;
581
	}
582
	@Override
583
    public void setSeriesPart(String seriesPart) {
584
		this.seriesPart = StringUtils.isBlank(seriesPart)? null : seriesPart;
585
	}
586

    
587
	@Override
588
    public String getOrganization() {
589
		return organization;
590
	}
591

    
592
	@Override
593
    public void setOrganization(String organization) {
594
		this.organization = StringUtils.isBlank(organization)? null : organization;
595
	}
596

    
597
	@Override
598
    public String getPublisher() {
599
		return publisher;
600
	}
601

    
602
	@Override
603
    public void setPublisher(String publisher) {
604
		this.publisher = StringUtils.isBlank(publisher)? null : publisher;
605
	}
606

    
607
	@Override
608
    public void setPublisher(String publisher, String placePublished){
609
		this.publisher = publisher;
610
		this.placePublished = placePublished;
611
	}
612

    
613
	@Override
614
    public String getPlacePublished() {
615
		return placePublished;
616
	}
617

    
618
	@Override
619
    public void setPlacePublished(String placePublished) {
620
		this.placePublished = StringUtils.isBlank(placePublished)? null: placePublished;
621
	}
622

    
623
	@Override
624
    public Institution getInstitution() {
625
		return institution;
626
	}
627

    
628
	@Override
629
    public void setInstitution(Institution institution) {
630
		this.institution = institution;
631
	}
632

    
633
	@Override
634
    public Institution getSchool() {
635
		return school;
636
	}
637

    
638
	@Override
639
    public void setSchool(Institution school) {
640
		this.school = school;
641
	}
642

    
643
	@Override
644
    public Reference getInReference() {
645
		return inReference;
646
	}
647

    
648
	@Override
649
    public void setInReference(Reference inReference) {
650
		this.inReference = inReference;
651
	}
652

    
653
	@Override
654
    public void setType(ReferenceType type) {
655
		if (type == null){
656
			this.type = ReferenceType.Generic;
657
		} else{
658
			this.type = type;
659
		}
660
	}
661
	@Override
662
    public ReferenceType getType() {
663
		return type;
664
	}
665

    
666
	/**
667
	 * Whether this reference is of the given type
668
	 *
669
	 * @param type
670
	 * @return
671
	 */
672
	@Override
673
    public boolean isOfType(ReferenceType type){
674
		return type == getType();
675
	}
676

    
677
	/**
678
	 * Returns a string representing the title of <i>this</i> reference. If a
679
	 * reference has different titles (for instance abbreviated and not
680
	 * abbreviated) then for each title a new instance must be created.
681
	 *
682
	 * @return  the title string of <i>this</i> reference
683
	 * @see 	#getCitation()
684
	 */
685
	@Override
686
    public String getTitle(){
687
		return this.title;
688
	}
689
	/**
690
	 * @see 	#getTitle()
691
	 */
692
	@Override
693
    public void setTitle(String title){
694
		this.title = StringUtils.isBlank(title)? null : title;
695
	}
696

    
697
	/**
698
	 * Returns the date (mostly only the year) of publication / creation of
699
	 * <i>this</i> reference.
700
	 */
701
	@Override
702
    public VerbatimTimePeriod getDatePublished(){
703
		return this.datePublished;
704
	}
705
	/**
706
	 * @see 	#getDatePublished()
707
	 */
708
	@Override
709
    public void setDatePublished(VerbatimTimePeriod datePublished){
710
		this.datePublished = datePublished;
711
	}
712
    @Override
713
    @Transient
714
    @Deprecated
715
    public VerbatimTimePeriod setDatePublished(TimePeriod datePublished){
716
        VerbatimTimePeriod newTimePeriod = VerbatimTimePeriod.toVerbatim(datePublished);
717
        setDatePublished(newTimePeriod);
718
        return newTimePeriod;
719
    }
720

    
721
	public boolean hasDatePublished(){
722
		boolean result =  ! ( (this.datePublished == null) || StringUtils.isBlank(datePublished.toString()));
723
		return result;
724
	}
725

    
726

    
727
	@Override
728
    public DateTime getAccessed() {
729
        return accessed;
730
    }
731

    
732
	@Override
733
    public void setAccessed(DateTime accessed) {
734
        this.accessed = accessed;
735
    }
736

    
737
	/**
738
	 * Returns the {@link eu.etaxonomy.cdm.model.agent.TeamOrPersonBase author (team)} who created the
739
	 * content of <i>this</i> reference.
740
	 *
741
	 * @return  the author (team) of <i>this</i> reference
742
	 * @see 	eu.etaxonomy.cdm.model.agent.TeamOrPersonBase
743
	 */
744
	@Override
745
    public TeamOrPersonBase getAuthorship(){
746
		return this.authorship;
747
	}
748

    
749
	/**
750
	 * @see #getAuthorship()
751
	 */
752
	@Override
753
    public void setAuthorship(TeamOrPersonBase authorship){
754
		this.authorship = authorship;
755
	}
756

    
757
	/**
758
	 * Returns the Uniform Resource Identifier (URI) corresponding to <i>this</i>
759
	 * reference. An URI is a string of characters used to identify a resource
760
	 * on the Internet.
761
	 *
762
	 * @return  the URI of <i>this</i> reference
763
	 */
764
	@Override
765
    public URI getUri(){
766
		return this.uri;
767
	}
768
	/**
769
	 * @see #getUri()
770
	 */
771
	@Override
772
    public void setUri(URI uri){
773
		this.uri = uri;
774
	}
775

    
776
	/**
777
	 * @return the referenceAbstract
778
	 */
779
	@Override
780
    public String getReferenceAbstract() {
781
		return referenceAbstract;
782
	}
783

    
784
	/**
785
	 * @param referenceAbstract the referenceAbstract to set
786
	 */
787
	@Override
788
    public void setReferenceAbstract(String referenceAbstract) {
789
		this.referenceAbstract = StringUtils.isBlank(referenceAbstract)? null : referenceAbstract;
790
	}
791

    
792

    
793
	/**
794
	 * Returns "true" if the isNomenclaturallyRelevant flag is set. This
795
	 * indicates that a {@link TaxonName taxon name} has been originally
796
	 * published in <i>this</i> reference following the rules of a
797
	 * {@link eu.etaxonomy.cdm.model.name.NomenclaturalCode nomenclature code} and is therefore used for
798
	 * nomenclatural citations. This flag will be set as soon as <i>this</i>
799
	 * reference is used as a nomenclatural reference for any taxon name.<BR>
800
	 * FIXME what happens if the only taxon name referencing this reference is not
801
	 * any longer using this reference as a nomenclatural reference. How does the
802
	 * reference get informed about the fact that it is not nomenclaturally relevant
803
	 * anymore?
804
	 */
805
	public boolean isNomenclaturallyRelevant(){
806
		return this.nomenclaturallyRelevant;
807
	}
808

    
809
	/**
810
	 * @see #isNomenclaturallyRelevant()
811
	 */
812
	public void setNomenclaturallyRelevant(boolean nomenclaturallyRelevant){
813
		this.nomenclaturallyRelevant = nomenclaturallyRelevant;
814
	}
815

    
816

    
817
//****************************************************  /
818

    
819
	@Transient
820
	@Override
821
	public void setTitleCaches(String cache){
822
	    this.setAbbrevTitleCache(cache, true);
823
	    this.setTitleCache(cache, true);
824
	}
825

    
826

    
827
	/**
828
	 * Returns a formatted string containing the entire reference citation,
829
	 * including authors, corresponding to <i>this</i> reference.
830
	 *
831
	 * @see  #generateTitle()
832
	 */
833
	// TODO implement
834
	@Transient
835
	public String getCitation(){
836
		if (getCacheStrategy() == null){
837
			logger.warn("No CacheStrategy defined for "+ this.getClass() + ": " + this.getUuid());
838
			return null;
839
		}else{
840
			return getCacheStrategy().getTitleCache(this);
841
		}
842
	}
843

    
844

    
845
	@Override
846
    public String generateTitle() {
847
		return super.generateTitle();
848
	}
849

    
850
    public String generateAbbrevTitle() {
851
		return getCacheStrategy().getFullAbbrevTitleString(this);
852
	}
853

    
854
	/**
855
	 * Returns a string representation for the year of publication / creation
856
	 * of <i>this</i> reference. If the {@link #getDatePublished() datePublished}
857
	 * of this reference contains more date information then (starting) year
858
	 * only the year is returned.
859
	 * than  attribute.
860
	 */
861
	@Override
862
    @Transient
863
	public String getYear(){
864
		VerbatimTimePeriod datePublished = this.getDatePublished();
865
		if (datePublished != null ){
866
			String result = getDatePublished().getYear();
867
			return result;
868
		}else{
869
			return null;
870
		}
871
	}
872

    
873
	/**
874
	 * Convenience method that returns a string representation for the publication date / creation
875
	 * of <i>this</i> reference. The string is obtained by
876
	 * {@link #getDatePublished()#toString() the string representation
877
	 * of the date published}.
878
	 */
879
	@Transient
880
	public String getDatePublishedString(){
881
		VerbatimTimePeriod datePublished = this.getDatePublished();
882
		if (datePublished != null ){
883
			return getDatePublished().toString();
884
		}else{
885
			return null;
886
		}
887
	}
888

    
889
	/**
890
     * Convenience method that returns a string representation for the publication date / creation
891
     * of <i>this</i> reference. The string is obtained by
892
     * {@link #getDatePublished()#toString() the string representation
893
     * of the date published}.
894
     */
895
    @Transient
896
    public String getTimePeriodPublishedString(){
897
        VerbatimTimePeriod datePublished = this.getDatePublished();
898
        if (datePublished != null ){
899
            return getDatePublished().getTimePeriod();
900
        }else{
901
            return null;
902
        }
903
    }
904

    
905

    
906

    
907
	@Override
908
    public int getParsingProblem(){
909
		return this.parsingProblem;
910
	}
911

    
912
	@Override
913
    public void setParsingProblem(int parsingProblem){
914
		this.parsingProblem = parsingProblem;
915
	}
916

    
917
	@Override
918
    public boolean hasProblem(){
919
		return parsingProblem != 0;
920
	}
921

    
922
	@Override
923
    public boolean hasProblem(ParserProblem problem) {
924
		return getParsingProblems().contains(problem);
925
	}
926

    
927
	@Override
928
    public int getProblemStarts(){
929
		return this.problemStarts;
930
	}
931

    
932
	@Override
933
    public void setProblemStarts(int start) {
934
		this.problemStarts = start;
935
	}
936

    
937
	@Override
938
    public int getProblemEnds(){
939
		return this.problemEnds;
940
	}
941

    
942
	@Override
943
    public void setProblemEnds(int end) {
944
		this.problemEnds = end;
945
	}
946

    
947
	@Override
948
    public void addParsingProblem(ParserProblem warning){
949
		parsingProblem = ParserProblem.addProblem(parsingProblem, warning);
950
	}
951

    
952
	@Override
953
    public void removeParsingProblem(ParserProblem problem) {
954
		parsingProblem = ParserProblem.removeProblem(parsingProblem, problem);
955
	}
956

    
957
	@Override
958
    @Transient
959
	public List<ParserProblem> getParsingProblems() {
960
		return ParserProblem.warningList(this.parsingProblem);
961
	}
962

    
963

    
964
	@Override
965
    @Transient
966
    public String getNomenclaturalCitation(String microReference) {
967
		String typeName = this.getType()== null ? "(no type defined)" : this.getType().getMessage();
968
		if (getCacheStrategy() == null){
969
			logger.warn("No CacheStrategy defined for "+ typeName + ": " + this.getUuid());
970
			return null;
971
		}else{
972
		    if (getCacheStrategy() instanceof INomenclaturalReferenceCacheStrategy){
973
				return cacheStrategy.getNomenclaturalCitation(this, microReference);
974
			}else {
975
				logger.warn("No INomenclaturalReferenceCacheStrategy defined for "+ typeName + ": " + this.getUuid());
976
				return null;
977
			}
978
		}
979
	}
980

    
981

    
982
	/**
983
	 * Generates, according to the {@link eu.etaxonomy.cdm.strategy.strategy.cache.reference.IReferenceBaseCacheStrategy cache strategy}
984
	 * assigned to <i>this</i> reference, a string that identifies <i>this</i>
985
	 * reference and returns it. This string may be stored in the inherited
986
	 * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} attribute.<BR>
987
	 * This method overrides the generic and inherited generateTitle method
988
	 * from {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity IdentifiableEntity}.
989
	 *
990
	 * @return  the string identifying <i>this</i> reference
991
	 * @see  	#getCitation()
992
	 * @see  	eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache()
993
	 * @see  	eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
994
	 * @see  	eu.etaxonomy.cdm.strategy.strategy.cache.common.IIdentifiableEntityCacheStrategy#getTitleCache()
995
	 */
996
//	@Override
997
//	public String generateTitle(){
998
//		if (cacheStrategy == null){
999
//			logger.warn("No CacheStrategy defined for Reference: " + this.getUuid());
1000
//			return null;
1001
//		}else{
1002
//			return cacheStrategy.getTitleCache(this);
1003
//		}
1004
//	}
1005

    
1006

    
1007

    
1008
//********** Casting methods ***********************************/
1009

    
1010
	/**
1011
	 * @return
1012
	 */
1013
	public IArticle castReferenceToArticle(){
1014
		setType(ReferenceType.Article);
1015
		return this;
1016
	}
1017

    
1018
	public IBook castReferenceToBook(){
1019
		setType(ReferenceType.Book);
1020
		return this;
1021
	}
1022

    
1023
	public IBookSection castReferenceToBookSection(){
1024
		setType(ReferenceType.BookSection);
1025
		return this;
1026
	}
1027

    
1028
	public ICdDvd castReferenceToCdDvd(){
1029
		setType(ReferenceType.CdDvd);
1030
		return this;
1031
	}
1032

    
1033
	public IDatabase castReferenceToDatabase(){
1034
		setType(ReferenceType.Database);
1035
		return this;
1036
	}
1037

    
1038
	public IGeneric castReferenceToGeneric(){
1039
		setType(ReferenceType.Generic);
1040
		return this;
1041
	}
1042

    
1043
	public IInProceedings castReferenceToInProceedings(){
1044
		setType(ReferenceType.InProceedings);
1045
		return this;
1046
	}
1047

    
1048
	public IJournal castReferenceToJournal(){
1049
		setType(ReferenceType.Journal);
1050
		return this;
1051
	}
1052

    
1053
	public IMap castReferenceToMap(){
1054
		setType(ReferenceType.Map);
1055
		return (IMap) this;
1056
	}
1057

    
1058
	public IPatent castReferenceToPatent(){
1059
		setType(ReferenceType.Patent);
1060
		return this;
1061
	}
1062

    
1063
	public IPersonalCommunication castReferenceToPersonalCommunication(){
1064
		setType(ReferenceType.PersonalCommunication);
1065
		return this;
1066
	}
1067

    
1068
	public IPrintSeries castReferenceToPrintSeries(){
1069
		setType(ReferenceType.PrintSeries);
1070
		return this;
1071
	}
1072

    
1073
	public IWebPage castReferenceToWebPage(){
1074
		setType(ReferenceType.WebPage);
1075
		return this;
1076
	}
1077

    
1078
	public IProceedings castReferenceToProceedings(){
1079
		setType(ReferenceType.Proceedings);
1080
		return this;
1081
	}
1082

    
1083
	public IReport castReferenceToReport(){
1084
		setType(ReferenceType.Report);
1085
		return this;
1086
	}
1087

    
1088
	public IThesis castReferenceToThesis(){
1089
		setType(ReferenceType.Thesis);
1090
		return this;
1091
	}
1092

    
1093

    
1094
	@Override
1095
    @Transient // prevent from being serialized by webservice
1096
	public IJournal getInJournal() {
1097
		IJournal journal = this.inReference;
1098
		return journal;
1099
	}
1100

    
1101
	@Override
1102
    public void setInJournal(IJournal journal) {
1103
		setInReference((Reference)journal);  //user setter to invoke aspect #1815
1104
	}
1105

    
1106
	@Override
1107
    @Transient // prevent from being serialized by webservice
1108
	public IPrintSeries getInSeries() {
1109
		return this.inReference;
1110
	}
1111

    
1112
	@Override
1113
    public void setInSeries(IPrintSeries inSeries) {
1114
	    setInReference((Reference)inSeries);  //user setter to invoke aspect  #1815
1115
	}
1116

    
1117
	@Override
1118
    @Transient // prevent from being serialized by webservice
1119
	public IBook getInBook() {
1120
		IBook book = this.inReference;
1121
		return book;
1122
	}
1123

    
1124
//********************** In-References *****************************************
1125

    
1126
	@Override
1127
    public void setInBook(IBook book) {
1128
	    setInReference((Reference)book);  //user setter to invoke aspect #1815
1129
	}
1130

    
1131
	@Override
1132
    @Transient // prevent from being serialized by webservice
1133
	public IProceedings getInProceedings() {
1134
		IProceedings proceedings = this.inReference;
1135
		return proceedings;
1136
	}
1137

    
1138
	@Override
1139
    public void setInProceedings(IProceedings proceeding) {
1140
        setInReference((Reference)proceeding);  //user setter to invoke aspect #1815
1141
	}
1142

    
1143
//*************************** CACHE STRATEGIES ******************************/
1144

    
1145
    @Override
1146
    public INomenclaturalReferenceCacheStrategy getCacheStrategy() {
1147
    	return this.cacheStrategy;
1148
    }
1149

    
1150
	@Override
1151
    public void setCacheStrategy(INomenclaturalReferenceCacheStrategy referenceCacheStrategy) {
1152
		this.cacheStrategy = referenceCacheStrategy;
1153
	}
1154

    
1155

    
1156

    
1157
//*********************** CLONE ********************************************************/
1158

    
1159
	/**
1160
	 * Clones <i>this</i> reference. This is a shortcut that enables to create
1161
	 * a new instance that differs only slightly from <i>this</i> reference by
1162
	 * modifying only some of the attributes.
1163
	 *
1164
	 * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
1165
	 * @see java.lang.Object#clone()
1166
	 */
1167
	@Override
1168
	public Object clone() {
1169
		try {
1170
			Reference result = (Reference)super.clone();
1171
			result.setDatePublished(datePublished != null? (VerbatimTimePeriod)datePublished.clone(): null);
1172
			//no changes to: title, authorship, hasProblem, nomenclaturallyRelevant, uri
1173
			return result;
1174
		} catch (CloneNotSupportedException e) {
1175
			logger.warn("Object does not implement cloneable");
1176
			e.printStackTrace();
1177
			return null;
1178
		}
1179
	}
1180

    
1181
//******************************* toString *****************************/
1182

    
1183
	@Override
1184
	public String toString() {
1185
		if (type != null){
1186
			String result = "Reference [type=" + type + ", id= " + this.getId() + ", uuid=" + this.uuid ;
1187
			result += title == null ? "" : ", title=" + title;
1188
			result += abbrevTitle == null ? "" : ", abbrevTitle=" + abbrevTitle;
1189
			result += "]";
1190
			return result;
1191
		}else{
1192
			return super.toString();
1193
		}
1194
	}
1195

    
1196

    
1197

    
1198

    
1199
}
1200

    
(24-24/28)