Project

General

Profile

Download (31.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.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
    public void setDatePublished(TimePeriod datePublished){
715
        setDatePublished(VerbatimTimePeriod.toVerbatim(datePublished));
716
    }
717

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

    
723

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

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

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

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

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

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

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

    
789

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

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

    
813

    
814
//****************************************************  /
815

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

    
823

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

    
841

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

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

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

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

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

    
902

    
903

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

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

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

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

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

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

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

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

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

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

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

    
960

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

    
978

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

    
1003

    
1004

    
1005
//********** Casting methods ***********************************/
1006

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1090

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

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

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

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

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

    
1121
//********************** In-References *****************************************
1122

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

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

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

    
1140
//*************************** CACHE STRATEGIES ******************************/
1141

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

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

    
1152

    
1153

    
1154
//*********************** CLONE ********************************************************/
1155

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

    
1178
//******************************* toString *****************************/
1179

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

    
1193

    
1194

    
1195

    
1196
}
1197

    
(24-24/28)