Project

General

Profile

Download (32.2 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.Table;
27
import javax.persistence.Transient;
28
import javax.validation.constraints.NotNull;
29
import javax.validation.constraints.Pattern;
30
import javax.xml.bind.annotation.XmlAccessType;
31
import javax.xml.bind.annotation.XmlAccessorType;
32
import javax.xml.bind.annotation.XmlAttribute;
33
import javax.xml.bind.annotation.XmlElement;
34
import javax.xml.bind.annotation.XmlIDREF;
35
import javax.xml.bind.annotation.XmlRootElement;
36
import javax.xml.bind.annotation.XmlSchemaType;
37
import javax.xml.bind.annotation.XmlTransient;
38
import javax.xml.bind.annotation.XmlType;
39
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
40

    
41
import org.apache.log4j.Logger;
42
import org.hibernate.annotations.Cascade;
43
import org.hibernate.annotations.CascadeType;
44
import org.hibernate.annotations.Parameter;
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.ExternallyManaged;
60
import eu.etaxonomy.cdm.model.common.IIntextReferenceTarget;
61
import eu.etaxonomy.cdm.model.common.TimePeriod;
62
import eu.etaxonomy.cdm.model.common.VerbatimTimePeriod;
63
import eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity;
64
import eu.etaxonomy.cdm.model.name.TaxonName;
65
import eu.etaxonomy.cdm.strategy.cache.reference.DefaultReferenceCacheStrategy;
66
import eu.etaxonomy.cdm.strategy.cache.reference.INomenclaturalReferenceCacheStrategy;
67
import eu.etaxonomy.cdm.strategy.match.Match;
68
import eu.etaxonomy.cdm.strategy.match.MatchMode;
69
import eu.etaxonomy.cdm.strategy.merge.Merge;
70
import eu.etaxonomy.cdm.strategy.merge.MergeMode;
71
import eu.etaxonomy.cdm.strategy.parser.ParserProblem;
72
import eu.etaxonomy.cdm.validation.Level2;
73
import eu.etaxonomy.cdm.validation.Level3;
74
import eu.etaxonomy.cdm.validation.annotation.InReference;
75
import eu.etaxonomy.cdm.validation.annotation.NoRecursiveInReference;
76
import eu.etaxonomy.cdm.validation.annotation.NullOrNotEmpty;
77
import eu.etaxonomy.cdm.validation.annotation.ReferenceCheck;
78

    
79
/**
80
 * The class for references (information sources). Originally
81
 * an abstract class with many subclasses. Now it is only
82
 * one class implementing many interfaces for safe use of different
83
 * types of references. E.g. if you want to edit a journal
84
 * you create a journal with {@link ReferenceFactory#newJournal()}
85
 * which returns an IJournal. Though this instance is an ordinary instance
86
 * of {@link Reference} by using IJournal you may not use attributes
87
 * not allowed for journals.<p>
88
 * References can be created via {@link ReferenceFactory} methods.
89
 * <P>
90
 * This class corresponds to: <ul>
91
 * <li> PublicationCitation according to the TDWG ontology
92
 * <li> Publication according to the TCS
93
 * <li> Reference according to the ABCD schema
94
 * </ul>
95
 *
96
 * @author m.doering
97
 * @since 08-Nov-2007 13:06:47
98
 */
99
@XmlAccessorType(XmlAccessType.FIELD)
100
@XmlType(name = "Reference", propOrder = {
101
	"type",
102
	"uri",
103
    "abbrevTitleCache",
104
    "protectedAbbrevTitleCache",
105
	"nomenclaturallyRelevant",
106
    "authorship",
107
    "referenceAbstract",
108
    "title",
109
    "abbrevTitle",
110
    "editor",
111
	"volume",
112
	"pages",
113
	"edition",
114
    "isbn",
115
    "issn",
116
    "doi",
117
    "seriesPart",
118
    "datePublished",
119
    "publisher",
120
    "placePublished",
121
    "institution",
122
    "school",
123
    "organization",
124
    "inReference",
125
    "accessed",
126
    "externallyManaged",
127
})
128
@XmlRootElement(name = "Reference")
129
@Entity
130
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
131
@Audited
132
@Table(name="Reference", indexes = { @javax.persistence.Index(name = "referenceTitleCacheIndex", columnList = "titleCache") })
133
//@InReference(groups=Level3.class)
134
@ReferenceCheck(groups=Level2.class)
135
@InReference(groups=Level3.class)
136
@NoRecursiveInReference(groups=Level3.class)  //may become Level1 in future  #
137
public class Reference
138
        extends IdentifiableMediaEntity<INomenclaturalReferenceCacheStrategy>
139
        implements IArticle, IBook, IPatent, IDatabase, IJournal, IBookSection,ICdDvd,
140
                   IGeneric,IInProceedings, IProceedings, IPrintSeries, IReport,
141
                   IThesis,IWebPage, IPersonalCommunication,
142
                   INomenclaturalReference, IReference, IIntextReferenceTarget {
143

    
144
    private static final long serialVersionUID = -2034764545042691295L;
145
	private static final Logger logger = Logger.getLogger(Reference.class);
146

    
147
//  from E+M import (still needed?)
148
//	@Column(length=255)
149
//  private String refAuthorString;
150
//	public String getRefAuthorString() {return refAuthorString;}
151
//  public void setRefAuthorString(String refAuthorString) {this.refAuthorString = refAuthorString;}
152

    
153
    @XmlAttribute(name ="type")
154
	@Column(name="refType")
155
	@NotNull
156
    @Type(type = "eu.etaxonomy.cdm.hibernate.EnumUserType",
157
    	parameters = {@Parameter(name  = "enumClass",
158
    	value = "eu.etaxonomy.cdm.model.reference.ReferenceType")}
159
    )
160
	@Audited
161
	protected ReferenceType type;
162

    
163
	//Title of the reference
164
	@XmlElement(name ="Title" )
165
	@Column(length=4096, name="title")
166
	@Lob
167
	@Field
168
	@Match(MatchMode.EQUAL_REQUIRED) //TODO correct? was EQUAL_REQUIRED before, but with abbrevTitle this is not realistic anymore
169
    //TODO Val #3379
170
//	@NullOrNotEmpty
171
	private String title;
172

    
173
	//Title of the reference
174
	@XmlElement(name ="AbbrevTitle" )
175
	@Field
176
	@Match(MatchMode.EQUAL)  //TODO check if this is correct
177
	@NullOrNotEmpty
178
	@Column(length=255)
179
	private String abbrevTitle;
180

    
181
	//Title of the reference
182
	@XmlElement(name ="AbbrevTitleCache" )
183
	@Field
184
	@Match(MatchMode.CACHE)
185
    //TODO Val #3379
186
//	@NotNull
187
	@Column(length=1024)
188
	private String abbrevTitleCache;
189

    
190
	@XmlElement(name = "protectedAbbrevTitleCache")
191
	@Merge(MergeMode.OR)
192
	private boolean protectedAbbrevTitleCache;
193

    
194
//********************************************************/
195

    
196

    
197
    @XmlElement(name = "Editor")
198
    @Field
199
    //TODO Val #3379
200
//    @NullOrNotEmpty
201
    @Column(length=255)
202
	protected String editor;
203

    
204
    @XmlElement(name = "Volume")
205
    @Field
206
    //TODO Val #3379
207
//    @NullOrNotEmpty
208
    @Column(length=255)
209
	protected String volume;
210

    
211
    @XmlElement(name = "Pages")
212
    @Field
213
    //TODO Val #3379
214
//    @NullOrNotEmpty
215
    @Column(length=255)
216
	protected String pages;
217

    
218
    @XmlElement(name = "Edition")
219
    @Field
220
    //TODO Val #3379
221
//    @NullOrNotEmpty
222
    @Column(length=255)
223
	protected String edition;
224

    
225
    @XmlElement(name = "ISBN")
226
    @Field
227
    //TODO Val #3379
228
//    @NullOrNotEmpty
229
    @Column(length=255)
230
	@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}")
231
	protected String isbn;
232

    
233
    @XmlElement(name = "Doi")
234
    @Field
235
    @FieldBridge(impl = DoiBridge.class)
236
    @Type(type="doiUserType")
237
    @Column(length=DOI.MAX_LENGTH)
238
    protected DOI doi;
239

    
240

    
241
	@XmlElement(name = "ISSN")
242
    @Field
243
    //TODO Val #3379
244
//	@NullOrNotEmpty
245
    @Column(length=255)
246
	@Pattern(regexp = "(?=.{9}$)\\d{4}([- ])\\d{4} (\\d|X)$", groups = Level2.class, message = "{eu.etaxonomy.cdm.model.reference.Reference.issn.message}")
247
	protected String issn;
248

    
249
    @XmlElement(name = "SeriesPart")
250
    @Field
251
    //TODO Val #3379
252
//    @NullOrNotEmpty
253
    @Column(length=255)
254
	protected String seriesPart;
255

    
256
	@XmlElement(name = "Organization")
257
    @Field
258
    //TODO Val #3379
259
//	@NullOrNotEmpty
260
    @Column(length=255)
261
	protected String organization;
262

    
263
	@XmlElement(name = "Publisher")
264
    @Field
265
    //TODO Val #3379
266
//	@NullOrNotEmpty
267
    @Column(length=255)
268
	protected String publisher;
269

    
270

    
271
	@XmlElement(name = "PlacePublished")
272
    @Field
273
    //TODO Val #3379
274
//	@NullOrNotEmpty
275
    @Column(length=255)
276
	protected String placePublished;
277

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

    
286
	@XmlElement(name = "School")
287
    @XmlIDREF
288
    @XmlSchemaType(name = "IDREF")
289
	@ManyToOne(fetch = FetchType.LAZY)
290
	@IndexedEmbedded
291
	@Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
292
	protected Institution school;
293

    
294
    @XmlElement(name = "InReference")
295
    @XmlIDREF
296
    @XmlSchemaType(name = "IDREF")
297
    @ManyToOne(fetch = FetchType.LAZY)
298
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
299
//  @InReference(groups=Level2.class)
300
   	protected Reference inReference;
301

    
302
//********************************************************/
303

    
304
	//The date range assigned to the reference. ISO Date range like. Flexible, year can be left out, etc
305
	@XmlElement(name ="DatePublished" )
306
	@Embedded
307
	@IndexedEmbedded
308
	private VerbatimTimePeriod datePublished = VerbatimTimePeriod.NewVerbatimInstance();
309

    
310
    //#5258
311
    @XmlElement(name = "Accessed", type= String.class)
312
    @XmlJavaTypeAdapter(DateTimeAdapter.class)
313
    @Type(type="dateTimeUserType")
314
    @Basic(fetch = FetchType.LAZY)
315
    @Match(MatchMode.EQUAL)
316
    @FieldBridge(impl = DateTimeBridge.class)
317
    private DateTime accessed;
318

    
319
    @XmlElement(name ="Abstract" )
320
	@Column(length=CLOB_LENGTH, name="referenceAbstract")
321
	@Lob
322
    @Field
323
    //TODO Val #3379
324
//	@NullOrNotEmpty
325
	private String referenceAbstract;  //abstract is a reserved term in Java
326

    
327

    
328
	//URIs like DOIs, LSIDs or Handles for this reference
329
	@XmlElement(name = "URI")
330
	@Field(analyze = Analyze.NO)
331
	@Type(type="uriUserType")
332
	private URI uri;
333

    
334
	//flag to subselect only references that could be useful for nomenclatural citations.
335
	//If a reference is used as a
336
	//nomenclatural reference in a name this flag should be automatically set
337
	@XmlElement(name = "IsNomenclaturallyRelevant")
338
	@Merge(MergeMode.OR)
339
	@Match(MatchMode.IGNORE)
340
	private boolean nomenclaturallyRelevant;
341

    
342
	@XmlElement(name = "Authorship")
343
	@XmlIDREF
344
	@XmlSchemaType(name = "IDREF")
345
	@ManyToOne(fetch = FetchType.LAZY)
346
	@IndexedEmbedded
347
	@Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
348
	private TeamOrPersonBase<?> authorship;
349

    
350
    private ExternallyManaged externallyManaged;
351

    
352
	@XmlAttribute
353
    @Match(MatchMode.IGNORE)
354
	private int parsingProblem = 0;
355

    
356
	@XmlAttribute
357
    @Match(MatchMode.IGNORE)
358
    private int problemStarts = -1;
359

    
360
    @XmlAttribute
361
    @Match(MatchMode.IGNORE)
362
    private int problemEnds = -1;
363

    
364

    
365
// *********************** CONSTRUCTOR ************************/
366

    
367
    protected Reference(){
368
		this(ReferenceType.Generic);  //just in case someone uses constructor
369
	}
370

    
371
	protected Reference(ReferenceType type) {
372
		super();
373
	    if (type == null){
374
			this.type = ReferenceType.Generic;
375
		} else{
376
			this.type = type;
377
		}
378
		this.setCacheStrategy(DefaultReferenceCacheStrategy.NewInstance());
379
	}
380

    
381
// *********************** LISTENER ************************/
382

    
383

    
384
	@Override
385
    public void initListener(){
386
        PropertyChangeListener listener = new PropertyChangeListener() {
387
            @Override
388
            public void propertyChange(PropertyChangeEvent ev) {
389
            	if (!ev.getPropertyName().equals("titleCache") && !ev.getPropertyName().equals("abbrevTitleCache") && !ev.getPropertyName().equals("cacheStrategy")){
390
            		if (! isProtectedTitleCache()){
391
            			titleCache = null;
392
            		}
393
            		if (! isProtectedAbbrevTitleCache()){
394
            			abbrevTitleCache = null;
395
            		}
396
            	}
397
            }
398
        };
399
        addPropertyChangeListener(listener);
400
    }
401

    
402

    
403
//*************************** GETTER / SETTER ******************************************/
404

    
405

    
406

    
407
    // @Transient  - must not be transient, since this property needs to to be included in all serializations produced by the remote layer
408
    @Override
409
    public String getTitleCache(){
410
        String result = super.getTitleCache();
411
        if (isBlank(result)){
412
            this.titleCache = this.getAbbrevTitleCache(true);
413
        }
414
        return titleCache;
415
    }
416

    
417
	@Override
418
	public String getAbbrevTitleCache() {
419
		return getAbbrevTitleCache(false);
420
	}
421

    
422
	/**
423
	 * Implements {@link #getAbbrevTitleCache()} but allows to
424
	 * avoid never ending recursions if both caches are empty
425
	 * avoidRecursion should only be <code>true</code> if called
426
	 * by {@link #getTitleCache()}
427
	 * @param avoidRecursion
428
	 * @return
429
	 */
430
	private String getAbbrevTitleCache(boolean avoidRecursion) {
431
        if (protectedAbbrevTitleCache){
432
            return this.abbrevTitleCache;
433
        }
434
        // is reference dirty, i.e. equal NULL?
435
        if (abbrevTitleCache == null){
436
            this.abbrevTitleCache = generateAbbrevTitle();
437
            this.abbrevTitleCache = getTruncatedCache(this.abbrevTitleCache) ;
438
        }
439
        if (isBlank(abbrevTitleCache) && !avoidRecursion){
440
            this.abbrevTitleCache = this.getTitleCache();
441
        }
442
        return abbrevTitleCache;
443
    }
444

    
445

    
446
    @Override
447
	@Deprecated
448
	public void setAbbrevTitleCache(String abbrevTitleCache) {
449
		this.abbrevTitleCache = abbrevTitleCache;
450
	}
451

    
452
	@Override
453
	public void setAbbrevTitleCache(String abbrevTitleCache, boolean isProtected) {
454
		this.protectedAbbrevTitleCache = isProtected;
455
		setAbbrevTitleCache(abbrevTitleCache);
456
	}
457

    
458
	@Override
459
	public boolean isProtectedAbbrevTitleCache() {
460
		return protectedAbbrevTitleCache;
461
	}
462

    
463
	@Override
464
	public void setProtectedAbbrevTitleCache(boolean protectedAbbrevTitleCache) {
465
		this.protectedAbbrevTitleCache = protectedAbbrevTitleCache;
466
	}
467

    
468
	@Override
469
	public String getAbbrevTitle() {
470
		return abbrevTitle;
471
	}
472

    
473
	@Override
474
	public void setAbbrevTitle(String abbrevTitle) {
475
		this.abbrevTitle = isBlank(abbrevTitle) ? null : abbrevTitle;
476
	}
477

    
478

    
479
	@Override
480
    public String getEditor() {
481
		return editor;
482
	}
483

    
484

    
485
	@Override
486
    public void setEditor(String editor) {
487
		this.editor = isBlank(editor)? null : editor;
488
	}
489

    
490
	@Override
491
    public String getVolume() {
492
		return volume;
493
	}
494

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

    
500
	@Override
501
    public String getPages() {
502
		return pages;
503
	}
504

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

    
510
	@Override
511
    public String getEdition() {
512
		return edition;
513
	}
514

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

    
520
	@Override
521
    public String getIsbn() {
522
		return isbn;
523
	}
524

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

    
530
	@Override
531
    public String getIssn() {
532
		return issn;
533
	}
534

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

    
540
    @Override
541
	public DOI getDoi() {
542
		return doi;
543
	}
544
    @Override
545
	public void setDoi(DOI doi) {
546
		this.doi = doi;
547
	}
548
    /**
549
     * Convenience method to retrieve doi as string
550
     */
551
    @Transient @XmlTransient @java.beans.Transient
552
    public String getDoiString() {
553
        return doi == null? null : doi.toString();
554
    }
555

    
556
	@Override
557
    public String getSeriesPart() {
558
		return seriesPart;
559
	}
560
	@Override
561
    public void setSeriesPart(String seriesPart) {
562
		this.seriesPart = isBlank(seriesPart)? null : seriesPart;
563
	}
564

    
565
	@Override
566
    public String getOrganization() {
567
		return organization;
568
	}
569

    
570
	@Override
571
    public void setOrganization(String organization) {
572
		this.organization = isBlank(organization)? null : organization;
573
	}
574

    
575
	@Override
576
    public String getPublisher() {
577
		return publisher;
578
	}
579

    
580
	@Override
581
    public void setPublisher(String publisher) {
582
		this.publisher = isBlank(publisher)? null : publisher;
583
	}
584

    
585
	@Override
586
    public void setPublisher(String publisher, String placePublished){
587
		this.publisher = publisher;
588
		this.placePublished = placePublished;
589
	}
590

    
591
	@Override
592
    public String getPlacePublished() {
593
		return placePublished;
594
	}
595

    
596
	@Override
597
    public void setPlacePublished(String placePublished) {
598
		this.placePublished = isBlank(placePublished)? null: placePublished;
599
	}
600

    
601
	@Override
602
    public Institution getInstitution() {
603
		return institution;
604
	}
605

    
606
	@Override
607
    public void setInstitution(Institution institution) {
608
		this.institution = institution;
609
	}
610

    
611
	@Override
612
    public Institution getSchool() {
613
		return school;
614
	}
615

    
616
	@Override
617
    public void setSchool(Institution school) {
618
		this.school = school;
619
	}
620

    
621
	@Override
622
    public Reference getInReference() {
623
		return inReference;
624
	}
625

    
626
	@Override
627
    public void setInReference(Reference inReference) {
628
		this.inReference = inReference;
629
	}
630

    
631
	@Override
632
    public void setType(ReferenceType type) {
633
		if (type == null){
634
			this.type = ReferenceType.Generic;
635
		} else{
636
			this.type = type;
637
		}
638
	}
639
	@Override
640
    public ReferenceType getType() {
641
		return type;
642
	}
643

    
644
	/**
645
	 * Whether this reference is of the given type
646
	 *
647
	 * @param type
648
	 * @return
649
	 */
650
	@Override
651
    public boolean isOfType(ReferenceType type){
652
		return type == getType();
653
	}
654

    
655
	/**
656
	 * Returns a string representing the title of <i>this</i> reference. If a
657
	 * reference has different titles (for instance abbreviated and not
658
	 * abbreviated) then for each title a new instance must be created.
659
	 *
660
	 * @return  the title string of <i>this</i> reference
661
	 * @see 	#getCitation()
662
	 */
663
	@Override
664
    public String getTitle(){
665
		return this.title;
666
	}
667
	/**
668
	 * @see 	#getTitle()
669
	 */
670
	@Override
671
    public void setTitle(String title){
672
		this.title = isBlank(title)? null : title;
673
	}
674

    
675
	/**
676
	 * Returns the date (mostly only the year) of publication / creation of
677
	 * <i>this</i> reference.
678
	 */
679
	@Override
680
    public VerbatimTimePeriod getDatePublished(){
681
		return this.datePublished;
682
	}
683
	/**
684
	 * @see 	#getDatePublished()
685
	 */
686
	@Override
687
    public void setDatePublished(VerbatimTimePeriod datePublished){
688
		this.datePublished = datePublished;
689
	}
690
    @Override
691
    @Transient
692
    @Deprecated
693
    public VerbatimTimePeriod setDatePublished(TimePeriod datePublished){
694
        VerbatimTimePeriod newTimePeriod = VerbatimTimePeriod.toVerbatim(datePublished);
695
        setDatePublished(newTimePeriod);
696
        return newTimePeriod;
697
    }
698

    
699
	public boolean hasDatePublished(){
700
		boolean result =  ! ( (this.datePublished == null) || isBlank(datePublished.toString()));
701
		return result;
702
	}
703

    
704

    
705
	@Override
706
    public DateTime getAccessed() {
707
        return accessed;
708
    }
709

    
710
	@Override
711
    public void setAccessed(DateTime accessed) {
712
        this.accessed = accessed;
713
    }
714

    
715
	/**
716
	 * Returns the {@link eu.etaxonomy.cdm.model.agent.TeamOrPersonBase author (team)} who created the
717
	 * content of <i>this</i> reference.
718
	 *
719
	 * @return  the author (team) of <i>this</i> reference
720
	 * @see 	eu.etaxonomy.cdm.model.agent.TeamOrPersonBase
721
	 */
722
	@Override
723
    public TeamOrPersonBase getAuthorship(){
724
		return this.authorship;
725
	}
726

    
727
	/**
728
	 * @see #getAuthorship()
729
	 */
730
	@Override
731
    public void setAuthorship(TeamOrPersonBase authorship){
732
		this.authorship = authorship;
733
	}
734

    
735
	/**
736
	 * Returns the Uniform Resource Identifier (URI) corresponding to <i>this</i>
737
	 * reference. An URI is a string of characters used to identify a resource
738
	 * on the Internet.
739
	 *
740
	 * @return  the URI of <i>this</i> reference
741
	 */
742
	@Override
743
    public URI getUri(){
744
		return this.uri;
745
	}
746
	/**
747
	 * @see #getUri()
748
	 */
749
	@Override
750
    public void setUri(URI uri){
751
		this.uri = uri;
752
	}
753

    
754
	/**
755
	 * @return the referenceAbstract
756
	 */
757
	@Override
758
    public String getReferenceAbstract() {
759
		return referenceAbstract;
760
	}
761

    
762
	/**
763
	 * @param referenceAbstract the referenceAbstract to set
764
	 */
765
	@Override
766
    public void setReferenceAbstract(String referenceAbstract) {
767
		this.referenceAbstract = isBlank(referenceAbstract)? null : referenceAbstract;
768
	}
769

    
770

    
771
	/**
772
	 * Returns "true" if the isNomenclaturallyRelevant flag is set. This
773
	 * indicates that a {@link TaxonName taxon name} has been originally
774
	 * published in <i>this</i> reference following the rules of a
775
	 * {@link eu.etaxonomy.cdm.model.name.NomenclaturalCode nomenclature code} and is therefore used for
776
	 * nomenclatural citations. This flag will be set as soon as <i>this</i>
777
	 * reference is used as a nomenclatural reference for any taxon name.<BR>
778
	 * FIXME what happens if the only taxon name referencing this reference is not
779
	 * any longer using this reference as a nomenclatural reference. How does the
780
	 * reference get informed about the fact that it is not nomenclaturally relevant
781
	 * anymore?
782
	 * @deprecated currently not supported and not in use, may be removed in future
783
	 */
784
	@Deprecated
785
    public boolean isNomenclaturallyRelevant(){
786
		return this.nomenclaturallyRelevant;
787
	}
788

    
789
	/**
790
	 * @see #isNomenclaturallyRelevant()
791
	 * @deprecated currently not supported and not in use, may be removed in future
792
	 */
793
	@Deprecated
794
	public void setNomenclaturallyRelevant(boolean nomenclaturallyRelevant){
795
		this.nomenclaturallyRelevant = nomenclaturallyRelevant;
796
	}
797

    
798

    
799
//****************************************************  /
800

    
801
	@Transient
802
	@Override
803
	public void setTitleCaches(String cache){
804
	    this.setAbbrevTitleCache(cache, true);
805
	    this.setTitleCache(cache, true);
806
	}
807

    
808

    
809
	/**
810
	 * Returns a formatted string containing the entire reference citation,
811
	 * including authors, corresponding to <i>this</i> reference.
812
	 *
813
	 * @see  #generateTitle()
814
	 */
815
	// TODO implement
816
	@Transient
817
	public String getCitation(){
818
		if (getCacheStrategy() == null){
819
			logger.warn("No CacheStrategy defined for "+ this.getClass() + ": " + this.getUuid());
820
			return null;
821
		}else{
822
			return getCacheStrategy().getTitleCache(this);
823
		}
824
	}
825

    
826

    
827
	@Override
828
    public String generateTitle() {
829
		return super.generateTitle();
830
	}
831

    
832
    public String generateAbbrevTitle() {
833
		return getCacheStrategy().getFullAbbrevTitleString(this);
834
	}
835

    
836
	/**
837
	 * Returns a string representation for the year of publication / creation
838
	 * of <i>this</i> reference. If the {@link #getDatePublished() datePublished}
839
	 * of this reference contains more date information then (starting) year
840
	 * only the year is returned.
841
	 * than  attribute.
842
	 */
843
	@Override
844
    @Transient
845
	public String getYear(){
846
		VerbatimTimePeriod datePublished = this.getDatePublished();
847
		if (datePublished != null ){
848
			String result = getDatePublished().getYear();
849
			return result;
850
		}else{
851
			return null;
852
		}
853
	}
854

    
855
	/**
856
	 * Convenience method that returns a string representation for the publication date / creation
857
	 * of <i>this</i> reference. The string is obtained by
858
	 * {@link #getDatePublished()#toString() the string representation
859
	 * of the date published}.
860
	 */
861
	@Transient
862
	public String getDatePublishedString(){
863
		VerbatimTimePeriod datePublished = this.getDatePublished();
864
		if (datePublished != null ){
865
			return getDatePublished().toString();
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 getTimePeriodPublishedString(){
879
        VerbatimTimePeriod datePublished = this.getDatePublished();
880
        if (datePublished != null ){
881
            return getDatePublished().getTimePeriod();
882
        }else{
883
            return null;
884
        }
885
    }
886

    
887
	@Override
888
    public int getParsingProblem(){
889
		return this.parsingProblem;
890
	}
891

    
892
	@Override
893
    public void setParsingProblem(int parsingProblem){
894
		this.parsingProblem = parsingProblem;
895
	}
896

    
897
	@Override
898
    public boolean hasProblem(){
899
		return parsingProblem != 0;
900
	}
901

    
902
	@Override
903
    public boolean hasProblem(ParserProblem problem) {
904
		return getParsingProblems().contains(problem);
905
	}
906

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

    
912
	@Override
913
    public void setProblemStarts(int start) {
914
		this.problemStarts = start;
915
	}
916

    
917
	@Override
918
    public int getProblemEnds(){
919
		return this.problemEnds;
920
	}
921

    
922
	@Override
923
    public void setProblemEnds(int end) {
924
		this.problemEnds = end;
925
	}
926

    
927
	@Override
928
    public void addParsingProblem(ParserProblem warning){
929
		parsingProblem = ParserProblem.addProblem(parsingProblem, warning);
930
	}
931

    
932
	@Override
933
    public void removeParsingProblem(ParserProblem problem) {
934
		parsingProblem = ParserProblem.removeProblem(parsingProblem, problem);
935
	}
936

    
937
	@Override
938
    @Transient
939
	public List<ParserProblem> getParsingProblems() {
940
		return ParserProblem.warningList(this.parsingProblem);
941
	}
942

    
943

    
944
	@Override
945
    @Transient
946
    public String getNomenclaturalCitation(String microReference) {
947
		String typeName = this.getType()== null ? "(no type defined)" : this.getType().getMessage();
948
		if (getCacheStrategy() == null){
949
			logger.warn("No CacheStrategy defined for "+ typeName + ": " + this.getUuid());
950
			return null;
951
		}else{
952
		    return cacheStrategy.getNomenclaturalCitation(this, microReference);
953
		}
954
	}
955

    
956
	/**
957
	 * Generates, according to the {@link eu.etaxonomy.cdm.strategy.strategy.cache.reference.IReferenceBaseCacheStrategy cache strategy}
958
	 * assigned to <i>this</i> reference, a string that identifies <i>this</i>
959
	 * reference and returns it. This string may be stored in the inherited
960
	 * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} attribute.<BR>
961
	 * This method overrides the generic and inherited generateTitle method
962
	 * from {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity IdentifiableEntity}.
963
	 *
964
	 * @return  the string identifying <i>this</i> reference
965
	 * @see  	#getCitation()
966
	 * @see  	eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache()
967
	 * @see  	eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
968
	 * @see  	eu.etaxonomy.cdm.strategy.strategy.cache.common.IIdentifiableEntityCacheStrategy#getTitleCache()
969
	 */
970
//	@Override
971
//	public String generateTitle(){
972
//		if (cacheStrategy == null){
973
//			logger.warn("No CacheStrategy defined for Reference: " + this.getUuid());
974
//			return null;
975
//		}else{
976
//			return cacheStrategy.getTitleCache(this);
977
//		}
978
//	}
979

    
980

    
981

    
982
//********** Casting methods ***********************************/
983

    
984
	/**
985
	 * @return
986
	 */
987
	public IArticle castReferenceToArticle(){
988
		setType(ReferenceType.Article);
989
		return this;
990
	}
991

    
992
	public IBook castReferenceToBook(){
993
		setType(ReferenceType.Book);
994
		return this;
995
	}
996

    
997
	public IBookSection castReferenceToBookSection(){
998
		setType(ReferenceType.BookSection);
999
		return this;
1000
	}
1001

    
1002
	public ICdDvd castReferenceToCdDvd(){
1003
		setType(ReferenceType.CdDvd);
1004
		return this;
1005
	}
1006

    
1007
	public IDatabase castReferenceToDatabase(){
1008
		setType(ReferenceType.Database);
1009
		return this;
1010
	}
1011

    
1012
	public IGeneric castReferenceToGeneric(){
1013
		setType(ReferenceType.Generic);
1014
		return this;
1015
	}
1016

    
1017
	public IInProceedings castReferenceToInProceedings(){
1018
		setType(ReferenceType.InProceedings);
1019
		return this;
1020
	}
1021

    
1022
	public IJournal castReferenceToJournal(){
1023
		setType(ReferenceType.Journal);
1024
		return this;
1025
	}
1026

    
1027
	public IMap castReferenceToMap(){
1028
		setType(ReferenceType.Map);
1029
		return (IMap) this;
1030
	}
1031

    
1032
	public IPatent castReferenceToPatent(){
1033
		setType(ReferenceType.Patent);
1034
		return this;
1035
	}
1036

    
1037
	public IPersonalCommunication castReferenceToPersonalCommunication(){
1038
		setType(ReferenceType.PersonalCommunication);
1039
		return this;
1040
	}
1041

    
1042
	public IPrintSeries castReferenceToPrintSeries(){
1043
		setType(ReferenceType.PrintSeries);
1044
		return this;
1045
	}
1046

    
1047
	public IWebPage castReferenceToWebPage(){
1048
		setType(ReferenceType.WebPage);
1049
		return this;
1050
	}
1051

    
1052
	public IProceedings castReferenceToProceedings(){
1053
		setType(ReferenceType.Proceedings);
1054
		return this;
1055
	}
1056

    
1057
	public IReport castReferenceToReport(){
1058
		setType(ReferenceType.Report);
1059
		return this;
1060
	}
1061

    
1062
	public IThesis castReferenceToThesis(){
1063
		setType(ReferenceType.Thesis);
1064
		return this;
1065
	}
1066

    
1067

    
1068
	@Override
1069
    @Transient // prevent from being serialized by webservice
1070
	public IJournal getInJournal() {
1071
		IJournal journal = this.inReference;
1072
		return journal;
1073
	}
1074

    
1075
	@Override
1076
    public void setInJournal(IJournal journal) {
1077
		setInReference((Reference)journal);  //user setter to invoke aspect #1815
1078
	}
1079

    
1080
	@Override
1081
    @Transient // prevent from being serialized by webservice
1082
	public IPrintSeries getInSeries() {
1083
		return this.inReference;
1084
	}
1085

    
1086
	@Override
1087
    public void setInSeries(IPrintSeries inSeries) {
1088
	    setInReference((Reference)inSeries);  //user setter to invoke aspect  #1815
1089
	}
1090

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

    
1098
//********************** In-References *****************************************
1099

    
1100
	@Override
1101
    public void setInBook(IBook book) {
1102
	    setInReference((Reference)book);  //user setter to invoke aspect #1815
1103
	}
1104

    
1105
	@Override
1106
    @Transient // prevent from being serialized by webservice
1107
	public IProceedings getInProceedings() {
1108
		IProceedings proceedings = this.inReference;
1109
		return proceedings;
1110
	}
1111

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

    
1117
//*************************** CACHE STRATEGIES ******************************/
1118

    
1119
    @Override
1120
    public INomenclaturalReferenceCacheStrategy getCacheStrategy() {
1121
    	return this.cacheStrategy;
1122
    }
1123

    
1124
	@Override
1125
    public void setCacheStrategy(INomenclaturalReferenceCacheStrategy referenceCacheStrategy) {
1126
		this.cacheStrategy = referenceCacheStrategy;
1127
	}
1128

    
1129
   @Override
1130
   public boolean updateCaches(){
1131
       //TODO shouldn't this be moved to the cache strategy?
1132
       if (this.equals(this.getInReference())){
1133
           String message = "-- invalid inreference (self-referencing) --";
1134
           String oldTitleCache = this.titleCache;
1135
           this.titleCache = message;
1136
           return !message.equals(oldTitleCache);
1137
       }
1138
       boolean result = super.updateCaches();
1139
       if (this.protectedAbbrevTitleCache == false){
1140
           String oldAbbrevTitleCache = this.abbrevTitleCache;
1141

    
1142
           String newAbbrevTitleCache = getTruncatedCache(cacheStrategy.getFullAbbrevTitleString(this));
1143
           if (newAbbrevTitleCache.equals("")){
1144
               newAbbrevTitleCache = cacheStrategy.getTitleCache(this);
1145
           }
1146

    
1147
           if ( oldAbbrevTitleCache == null   || ! oldAbbrevTitleCache.equals(newAbbrevTitleCache) ){
1148
                this.setAbbrevTitleCache(null, false);
1149
                String newCache = this.getAbbrevTitleCache();
1150

    
1151
                if (newCache == null){
1152
                    logger.warn("New abbrevCache should never be null");
1153
                }
1154
                if (oldAbbrevTitleCache == null){
1155
                    logger.info("oldAbbrevTitleCache was illegaly null and has been fixed");
1156
                }
1157
                result = true;
1158
            }
1159
        }
1160
        return result;
1161
    }
1162

    
1163

    
1164
//*********************** CLONE ********************************************************/
1165

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

    
1188
//******************************* toString *****************************/
1189

    
1190
	@Override
1191
	public String toString() {
1192
		if (type != null){
1193
			String result = "Reference [type=" + type  ;
1194
			result += title == null ? "" : ", title=" + title;
1195
			result += abbrevTitle == null ? "" : ", abbrevTitle=" + abbrevTitle;
1196
			result += ", id= " + this.getId() + ", uuid=" + this.uuid;
1197
			result += "]";
1198
			return result;
1199
		}else{
1200
			return super.toString();
1201
		}
1202
	}
1203

    
1204

    
1205

    
1206

    
1207
}
1208

    
(33-33/38)