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.strategy.cache.reference.DefaultReferenceCacheStrategy;
64
import eu.etaxonomy.cdm.strategy.cache.reference.INomenclaturalReferenceCacheStrategy;
65
import eu.etaxonomy.cdm.strategy.match.Match;
66
import eu.etaxonomy.cdm.strategy.match.MatchMode;
67
import eu.etaxonomy.cdm.strategy.merge.Merge;
68
import eu.etaxonomy.cdm.strategy.merge.MergeMode;
69
import eu.etaxonomy.cdm.strategy.parser.ParserProblem;
70
import eu.etaxonomy.cdm.validation.Level2;
71
import eu.etaxonomy.cdm.validation.Level3;
72
import eu.etaxonomy.cdm.validation.annotation.InReference;
73
import eu.etaxonomy.cdm.validation.annotation.NoRecursiveInReference;
74
import eu.etaxonomy.cdm.validation.annotation.NullOrNotEmpty;
75
import eu.etaxonomy.cdm.validation.annotation.ReferenceCheck;
76

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

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

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

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

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

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

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

    
183
//********************************************************/
184

    
185

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

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

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

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

    
214
    @XmlElement(name = "ISBN")
215
    @Field
216
    //TODO Val #3379
217
//    @NullOrNotEmpty
218
    @Column(length=255)
219
	@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}")
220
	protected String isbn;
221

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

    
229

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

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

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

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

    
259

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

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

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

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

    
291
//********************************************************/
292

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

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

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

    
316

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

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

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

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

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

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

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

    
355
    //attributes for externally managed
356

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

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

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

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

    
385
// *********************** CONSTRUCTOR ************************/
386

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

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

    
401
// *********************** LISTENER ************************/
402

    
403

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

    
422

    
423
//*************************** GETTER / SETTER ******************************************/
424

    
425

    
426

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

    
437
	@Override
438
	public String getAbbrevTitleCache() {
439
		return getAbbrevTitleCache(false);
440
	}
441

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

    
465

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

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

    
478
	@Override
479
	public boolean isProtectedAbbrevTitleCache() {
480
		return protectedAbbrevTitleCache;
481
	}
482

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

    
488
	@Override
489
	public String getAbbrevTitle() {
490
		return abbrevTitle;
491
	}
492

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

    
498

    
499
	@Override
500
    public String getEditor() {
501
		return editor;
502
	}
503

    
504

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

    
510
	@Override
511
    public String getVolume() {
512
		return volume;
513
	}
514

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

    
520
	@Override
521
    public String getPages() {
522
		return pages;
523
	}
524

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

    
530
	@Override
531
    public String getEdition() {
532
		return edition;
533
	}
534

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

    
540
	@Override
541
    public String getIsbn() {
542
		return isbn;
543
	}
544

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

    
550
	@Override
551
    public String getIssn() {
552
		return issn;
553
	}
554

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

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

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

    
585
	@Override
586
    public String getOrganization() {
587
		return organization;
588
	}
589

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

    
595
	@Override
596
    public String getPublisher() {
597
		return publisher;
598
	}
599

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

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

    
611
	@Override
612
    public String getPlacePublished() {
613
		return placePublished;
614
	}
615

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

    
621
	@Override
622
    public Institution getInstitution() {
623
		return institution;
624
	}
625

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

    
631
	@Override
632
    public Institution getSchool() {
633
		return school;
634
	}
635

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

    
641
	@Override
642
    public Reference getInReference() {
643
		return inReference;
644
	}
645

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

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

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

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

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

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

    
724

    
725
	@Override
726
    public DateTime getAccessed() {
727
        return accessed;
728
    }
729

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

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

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

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

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

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

    
790

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

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

    
814

    
815
//****************************************************  /
816

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

    
824

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

    
842

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

    
848
    public String generateAbbrevTitle() {
849
		return getCacheStrategy().getFullAbbrevTitleString(this);
850
	}
851

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

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

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

    
903

    
904

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

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

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

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

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

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

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

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

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

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

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

    
961

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

    
979

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

    
1004

    
1005

    
1006
//********** Casting methods ***********************************/
1007

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1091

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

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

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

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

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

    
1122
//********************** In-References *****************************************
1123

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

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

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

    
1141
//*************************** CACHE STRATEGIES ******************************/
1142

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

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

    
1153

    
1154

    
1155
//*********************** CLONE ********************************************************/
1156

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

    
1179
//******************************* toString *****************************/
1180

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

    
1194

    
1195

    
1196

    
1197
}
1198

    
(24-24/29)