Project

General

Profile

Download (30.6 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2007 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9

    
10
package eu.etaxonomy.cdm.model.reference;
11

    
12
import java.beans.PropertyChangeEvent;
13
import java.beans.PropertyChangeListener;
14
import java.net.URI;
15
import java.util.List;
16

    
17
import javax.persistence.Column;
18
import javax.persistence.Embedded;
19
import javax.persistence.Entity;
20
import javax.persistence.FetchType;
21
import javax.persistence.Inheritance;
22
import javax.persistence.InheritanceType;
23
import javax.persistence.Lob;
24
import javax.persistence.ManyToOne;
25
import javax.persistence.Transient;
26
import javax.validation.constraints.NotNull;
27
import javax.validation.constraints.Pattern;
28
import javax.xml.bind.annotation.XmlAccessType;
29
import javax.xml.bind.annotation.XmlAccessorType;
30
import javax.xml.bind.annotation.XmlAttribute;
31
import javax.xml.bind.annotation.XmlElement;
32
import javax.xml.bind.annotation.XmlIDREF;
33
import javax.xml.bind.annotation.XmlRootElement;
34
import javax.xml.bind.annotation.XmlSchemaType;
35
import javax.xml.bind.annotation.XmlType;
36

    
37
import org.apache.commons.lang.StringUtils;
38
import org.apache.log4j.Logger;
39
import org.hibernate.annotations.Cascade;
40
import org.hibernate.annotations.CascadeType;
41
import org.hibernate.annotations.Table;
42
import org.hibernate.annotations.Type;
43
import org.hibernate.envers.Audited;
44
import org.hibernate.search.annotations.Analyze;
45
import org.hibernate.search.annotations.Field;
46
import org.hibernate.search.annotations.FieldBridge;
47
import org.hibernate.search.annotations.IndexedEmbedded;
48

    
49
import eu.etaxonomy.cdm.common.DOI;
50
import eu.etaxonomy.cdm.hibernate.search.DoiBridge;
51
import eu.etaxonomy.cdm.model.agent.Institution;
52
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
53
import eu.etaxonomy.cdm.model.common.TimePeriod;
54
import eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity;
55
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
56
import eu.etaxonomy.cdm.strategy.cache.reference.ArticleDefaultCacheStrategy;
57
import eu.etaxonomy.cdm.strategy.cache.reference.BookDefaultCacheStrategy;
58
import eu.etaxonomy.cdm.strategy.cache.reference.BookSectionDefaultCacheStrategy;
59
import eu.etaxonomy.cdm.strategy.cache.reference.GenericDefaultCacheStrategy;
60
import eu.etaxonomy.cdm.strategy.cache.reference.INomenclaturalReferenceCacheStrategy;
61
import eu.etaxonomy.cdm.strategy.cache.reference.IReferenceBaseCacheStrategy;
62
import eu.etaxonomy.cdm.strategy.cache.reference.JournalDefaultCacheStrategy;
63
import eu.etaxonomy.cdm.strategy.cache.reference.ReferenceDefaultCacheStrategy;
64
import eu.etaxonomy.cdm.strategy.match.Match;
65
import eu.etaxonomy.cdm.strategy.match.MatchMode;
66
import eu.etaxonomy.cdm.strategy.merge.Merge;
67
import eu.etaxonomy.cdm.strategy.merge.MergeMode;
68
import eu.etaxonomy.cdm.strategy.parser.ParserProblem;
69
import eu.etaxonomy.cdm.validation.Level2;
70
import eu.etaxonomy.cdm.validation.Level3;
71
import eu.etaxonomy.cdm.validation.annotation.InReference;
72
import eu.etaxonomy.cdm.validation.annotation.NoRecursiveInReference;
73
import eu.etaxonomy.cdm.validation.annotation.NullOrNotEmpty;
74
import eu.etaxonomy.cdm.validation.annotation.ReferenceCheck;
75

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

    
128
    private static final long serialVersionUID = -2034764545042691295L;
129
	private static final Logger logger = Logger.getLogger(Reference.class);
130

    
131
	@XmlAttribute(name ="type")
132
	@Column(name="refType")
133
	@NotNull
134
    @Type(type = "eu.etaxonomy.cdm.hibernate.EnumUserType",
135
    	parameters = {@org.hibernate.annotations.Parameter(name  = "enumClass", value = "eu.etaxonomy.cdm.model.reference.ReferenceType")}
136
    )
137
	@Audited
138
	protected ReferenceType type;
139

    
140
	//Title of the reference
141
	@XmlElement(name ="Title" )
142
	@Column(length=4096, name="title")
143
	@Lob
144
	@Field
145
	@Match(MatchMode.EQUAL_REQUIRED)
146
    //TODO Val #3379
147
//	@NullOrNotEmpty
148
	private String title;
149

    
150
	//Title of the reference
151
	@XmlElement(name ="AbbrevTitle" )
152
	@Field
153
	@Match(MatchMode.EQUAL)  //TODO check if this is correct
154
	@NullOrNotEmpty
155
	@Column(length=255)
156
	private String abbrevTitle;
157

    
158
	//Title of the reference
159
	@XmlElement(name ="AbbrevTitleCache" )
160
	@Field
161
	@Match(MatchMode.CACHE)
162
    //TODO Val #3379
163
//	@NotNull
164
	@Column(length=1024)
165
	private String abbrevTitleCache;
166

    
167
	@XmlElement(name = "protectedAbbrevTitleCache")
168
	@Merge(MergeMode.OR)
169
	private boolean protectedAbbrevTitleCache;
170

    
171
//********************************************************/
172

    
173

    
174
    @XmlElement(name = "Editor")
175
    @Field
176
    //TODO Val #3379
177
//    @NullOrNotEmpty
178
    @Column(length=255)
179
	protected String editor;
180

    
181
    @XmlElement(name = "Volume")
182
    @Field
183
    //TODO Val #3379
184
//    @NullOrNotEmpty
185
    @Column(length=255)
186
	protected String volume;
187

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

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

    
202
    @XmlElement(name = "ISBN")
203
    @Field
204
    //TODO Val #3379
205
//    @NullOrNotEmpty
206
    @Column(length=255)
207
	@Pattern(regexp = "(?=.{13}$)\\d{1,5}([- ])\\d{1,7}\\1\\d{1,6}\\1(\\d|X)$", groups = Level2.class, message = "{eu.etaxonomy.cdm.model.reference.Reference.isbn.message}")
208
	protected String isbn;
209

    
210
    @XmlElement(name = "Doi")
211
    @Field
212
    @FieldBridge(impl = DoiBridge.class)
213
    @Type(type="doiUserType")
214
    @Column(length=DOI.MAX_LENGTH)
215
    protected DOI doi;
216

    
217

    
218
	@XmlElement(name = "ISSN")
219
    @Field
220
    //TODO Val #3379
221
//	@NullOrNotEmpty
222
    @Column(length=255)
223
	@Pattern(regexp = "(?=.{9}$)\\d{4}([- ])\\d{4} (\\d|X)$", groups = Level2.class, message = "{eu.etaxonomy.cdm.model.reference.Reference.issn.message}")
224
	protected String issn;
225

    
226
    @XmlElement(name = "SeriesPart")
227
    @Field
228
    //TODO Val #3379
229
//    @NullOrNotEmpty
230
    @Column(length=255)
231
	protected String seriesPart;
232

    
233
	@XmlElement(name = "Organization")
234
    @Field
235
    //TODO Val #3379
236
//	@NullOrNotEmpty
237
    @Column(length=255)
238
	protected String organization;
239

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

    
247

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

    
255
	@XmlElement(name = "Institution")
256
	@XmlIDREF
257
	@XmlSchemaType(name = "IDREF")
258
	@ManyToOne(fetch = FetchType.LAZY)
259
	@IndexedEmbedded
260
	@Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
261
	protected Institution institution;
262

    
263
	@XmlElement(name = "School")
264
    @XmlIDREF
265
    @XmlSchemaType(name = "IDREF")
266
	@ManyToOne(fetch = FetchType.LAZY)
267
	@IndexedEmbedded
268
	@Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
269
	protected Institution school;
270

    
271
    @XmlElement(name = "InReference")
272
    @XmlIDREF
273
    @XmlSchemaType(name = "IDREF")
274
    @ManyToOne(fetch = FetchType.LAZY)
275
//    @IndexedEmbedded
276
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
277
   // @InReference(groups=Level2.class)
278
   	protected Reference inReference;
279

    
280
//********************************************************/
281

    
282
	//The date range assigned to the reference. ISO Date range like. Flexible, year can be left out, etc
283
	@XmlElement(name ="DatePublished" )
284
	@Embedded
285
	@IndexedEmbedded
286
	private TimePeriod datePublished = TimePeriod.NewInstance();
287

    
288
	@XmlElement(name ="Abstract" )
289
	@Column(length=65536, name="referenceAbstract")
290
	@Lob
291
    @Field
292
    //TODO Val #3379
293
//	@NullOrNotEmpty
294
	private String referenceAbstract;  //abstract is a reserved term in Java
295

    
296

    
297
	//URIs like DOIs, LSIDs or Handles for this reference
298
	@XmlElement(name = "URI")
299
	@Field(analyze = Analyze.NO)
300
	@Type(type="uriUserType")
301
	private URI uri;
302

    
303
	//flag to subselect only references that could be useful for nomenclatural citations. If a reference is used as a
304
	//nomenclatural reference in a name this flag should be automatically set
305
	@XmlElement(name = "IsNomenclaturallyRelevant")
306
	@Merge(MergeMode.OR)
307
	private boolean nomenclaturallyRelevant;
308

    
309
	@XmlElement(name = "Authorship")
310
	@XmlIDREF
311
	@XmlSchemaType(name = "IDREF")
312
	@ManyToOne(fetch = FetchType.LAZY)
313
	@IndexedEmbedded
314
	@Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
315
	private TeamOrPersonBase<?> authorship;
316

    
317
	@XmlAttribute
318
    @Match(MatchMode.IGNORE)
319
	private int parsingProblem = 0;
320

    
321
	@XmlAttribute
322
    @Match(MatchMode.IGNORE)
323
    private int problemStarts = -1;
324

    
325
    @XmlAttribute
326
    @Match(MatchMode.IGNORE)
327
    private int problemEnds = -1;
328

    
329
    @Transient
330
    @XmlAttribute
331
    @Match(MatchMode.IGNORE)
332
	private boolean cacheStrategyRectified = false;
333

    
334
    protected Reference(){
335
		this(ReferenceType.Generic);  //just in case someone uses constructor
336
	}
337

    
338
	protected Reference(ReferenceType type) {
339
		if (type == null){
340
			this.type = ReferenceType.Generic;
341
		} else{
342
			this.type = type;
343
		}
344
	}
345

    
346
	@Override
347
    public void initListener(){
348
        PropertyChangeListener listener = new PropertyChangeListener() {
349
            @Override
350
            public void propertyChange(PropertyChangeEvent ev) {
351
            	if (!ev.getPropertyName().equals("titleCache") && !ev.getPropertyName().equals("abbrevTitleCache") && !ev.getPropertyName().equals("cacheStrategy")){
352
            		if (! isProtectedTitleCache()){
353
            			titleCache = null;
354
            		}
355
            		if (! isProtectedAbbrevTitleCache()){
356
            			abbrevTitleCache = null;
357
            		}
358
            	}
359
            }
360
        };
361
        addPropertyChangeListener(listener);
362
    }
363

    
364

    
365
//*************************** GETTER / SETTER ******************************************/
366

    
367

    
368
	@Override
369
	public String getAbbrevTitleCache() {
370
		if (protectedAbbrevTitleCache){
371
            return this.abbrevTitleCache;
372
        }
373
        // is title dirty, i.e. equal NULL?
374
        if (abbrevTitleCache == null){
375
            this.abbrevTitleCache = generateAbbrevTitle();
376
            this.abbrevTitleCache = getTruncatedCache(this.abbrevTitleCache) ;
377
        }
378
        return abbrevTitleCache;
379
	}
380

    
381
	@Override
382
	@Deprecated
383
	public void setAbbrevTitleCache(String abbrevTitleCache) {
384
		this.abbrevTitleCache = abbrevTitleCache;
385
	}
386

    
387
	@Override
388
	public void setAbbrevTitleCache(String abbrevTitleCache, boolean isProtected) {
389
		this.protectedAbbrevTitleCache = isProtected;
390
		setAbbrevTitleCache(abbrevTitleCache);
391
	}
392

    
393
	@Override
394
	public boolean isProtectedAbbrevTitleCache() {
395
		return protectedAbbrevTitleCache;
396
	}
397

    
398
	@Override
399
	public void setProtectedAbbrevTitleCache(boolean protectedAbbrevTitleCache) {
400
		this.protectedAbbrevTitleCache = protectedAbbrevTitleCache;
401
	}
402

    
403
	@Override
404
	public String getAbbrevTitle() {
405
		return abbrevTitle;
406
	}
407

    
408
	@Override
409
	public void setAbbrevTitle(String abbrevTitle) {
410
		this.abbrevTitle = StringUtils.isBlank(abbrevTitle) ? null : abbrevTitle;
411
	}
412

    
413

    
414
	@Override
415
    public String getEditor() {
416
		return editor;
417
	}
418

    
419

    
420
	@Override
421
    public void setEditor(String editor) {
422
		this.editor = StringUtils.isBlank(editor)? null : editor;
423
	}
424

    
425
	@Override
426
    public String getVolume() {
427
		return volume;
428
	}
429

    
430
	@Override
431
    public void setVolume(String volume) {
432
		this.volume = StringUtils.isBlank(volume)? null : volume;
433
	}
434

    
435
	@Override
436
    public String getPages() {
437
		return pages;
438
	}
439

    
440
	@Override
441
    public void setPages(String pages) {
442
		this.pages = StringUtils.isBlank(pages)? null : pages;
443
	}
444

    
445
	@Override
446
    public String getEdition() {
447
		return edition;
448
	}
449

    
450
	@Override
451
    public void setEdition(String edition) {
452
		this.edition = StringUtils.isBlank(edition)? null : edition;
453
	}
454

    
455
	@Override
456
    public String getIsbn() {
457
		return isbn;
458
	}
459

    
460
	@Override
461
    public void setIsbn(String isbn) {
462
		this.isbn = StringUtils.isBlank(isbn)? null : isbn;
463
	}
464

    
465
	@Override
466
    public String getIssn() {
467
		return issn;
468
	}
469

    
470
	@Override
471
    public void setIssn(String issn) {
472
		this.issn = StringUtils.isBlank(issn)? null : issn;
473
	}
474

    
475
    @Override
476
	public DOI getDoi() {
477
		return doi;
478
	}
479

    
480
    @Override
481
	public void setDoi(DOI doi) {
482
		this.doi = doi;
483
	}
484

    
485
	@Override
486
    public String getSeriesPart() {
487
		return seriesPart;
488
	}
489

    
490
	@Override
491
    public void setSeriesPart(String seriesPart) {
492
		this.seriesPart = StringUtils.isBlank(seriesPart)? null : seriesPart;
493
	}
494

    
495
	@Override
496
    public String getOrganization() {
497
		return organization;
498
	}
499

    
500
	@Override
501
    public void setOrganization(String organization) {
502
		this.organization = StringUtils.isBlank(organization)? null : organization;
503
	}
504

    
505
	@Override
506
    public String getPublisher() {
507
		return publisher;
508
	}
509

    
510
	@Override
511
    public void setPublisher(String publisher) {
512
		this.publisher = StringUtils.isBlank(publisher)? null : publisher;
513
	}
514

    
515
	@Override
516
    public void setPublisher(String publisher, String placePublished){
517
		this.publisher = publisher;
518
		this.placePublished = placePublished;
519
	}
520

    
521
	@Override
522
    public String getPlacePublished() {
523
		return placePublished;
524
	}
525

    
526
	@Override
527
    public void setPlacePublished(String placePublished) {
528
		this.placePublished = StringUtils.isBlank(placePublished)? null: placePublished;
529
	}
530

    
531
	@Override
532
    public Institution getInstitution() {
533
		return institution;
534
	}
535

    
536
	@Override
537
    public void setInstitution(Institution institution) {
538
		this.institution = institution;
539
	}
540

    
541
	@Override
542
    public Institution getSchool() {
543
		return school;
544
	}
545

    
546
	@Override
547
    public void setSchool(Institution school) {
548
		this.school = school;
549
	}
550

    
551
	@Override
552
    public Reference getInReference() {
553
		return inReference;
554
	}
555

    
556
	@Override
557
    public void setInReference(Reference inReference) {
558
		this.inReference = inReference;
559
	}
560

    
561
	@Override
562
    public void setType(ReferenceType type) {
563
		if (type == null){
564
			this.type = ReferenceType.Generic;
565
		} else{
566
			this.type = type;
567
		}
568
		this.setCacheStrategy(type.getCacheStrategy());
569

    
570
	}
571

    
572
	/**
573
	 * @return the type
574
	 */
575
	@Override
576
    public ReferenceType getType() {
577
		return type;
578
	}
579

    
580
	/**
581
	 * Whether this reference is of the given type
582
	 *
583
	 * @param type
584
	 * @return
585
	 */
586
	@Override
587
    public boolean isOfType(ReferenceType type){
588
		return type == getType();
589
	}
590

    
591
	/**
592
	 * Returns a string representing the title of <i>this</i> reference. If a
593
	 * reference has different titles (for instance abbreviated and not
594
	 * abbreviated) then for each title a new instance must be created.
595
	 *
596
	 * @return  the title string of <i>this</i> reference
597
	 * @see 	#getCitation()
598
	 */
599
	@Override
600
    public String getTitle(){
601
		return this.title;
602
	}
603
	/**
604
	 * @see 	#getTitle()
605
	 */
606
	@Override
607
    public void setTitle(String title){
608
		this.title = StringUtils.isBlank(title)? null : title;
609
	}
610

    
611
	/**
612
	 * Returns the date (mostly only the year) of publication / creation of
613
	 * <i>this</i> reference.
614
	 */
615
	@Override
616
    public TimePeriod getDatePublished(){
617
		return this.datePublished;
618
	}
619
	/**
620
	 * @see 	#getDatePublished()
621
	 */
622
	@Override
623
    public void setDatePublished(TimePeriod datePublished){
624
		this.datePublished = datePublished;
625
	}
626

    
627
	public boolean hasDatePublished(){
628
		boolean result =  ! ( (this.datePublished == null) || StringUtils.isBlank(datePublished.toString()));
629
		return result;
630
	}
631

    
632
	/**
633
	 * Returns the {@link eu.etaxonomy.cdm.model.agent.TeamOrPersonBase author (team)} who created the
634
	 * content of <i>this</i> reference.
635
	 *
636
	 * @return  the author (team) of <i>this</i> reference
637
	 * @see 	eu.etaxonomy.cdm.model.agent.TeamOrPersonBase
638
	 */
639
	@Override
640
    public TeamOrPersonBase getAuthorship(){
641
		return this.authorship;
642
	}
643

    
644
	/**
645
	 * @see #getAuthorship()
646
	 */
647
	@Override
648
    public void setAuthorship(TeamOrPersonBase authorship){
649
		this.authorship = authorship;
650
	}
651

    
652
	/**
653
	 * Returns the Uniform Resource Identifier (URI) corresponding to <i>this</i>
654
	 * reference. An URI is a string of characters used to identify a resource
655
	 * on the Internet.
656
	 *
657
	 * @return  the URI of <i>this</i> reference
658
	 */
659
	@Override
660
    public URI getUri(){
661
		return this.uri;
662
	}
663
	/**
664
	 * @see #getUri()
665
	 */
666
	@Override
667
    public void setUri(URI uri){
668
		this.uri = uri;
669
	}
670

    
671
	/**
672
	 * @return the referenceAbstract
673
	 */
674
	@Override
675
    public String getReferenceAbstract() {
676
		return referenceAbstract;
677
	}
678

    
679
	/**
680
	 * @param referenceAbstract the referenceAbstract to set
681
	 */
682
	@Override
683
    public void setReferenceAbstract(String referenceAbstract) {
684
		this.referenceAbstract = StringUtils.isBlank(referenceAbstract)? null : referenceAbstract;
685
	}
686

    
687

    
688
	/**
689
	 * Returns "true" if the isNomenclaturallyRelevant flag is set. This
690
	 * indicates that a {@link TaxonNameBase taxon name} has been originally
691
	 * published in <i>this</i> reference following the rules of a
692
	 * {@link eu.etaxonomy.cdm.model.name.NomenclaturalCode nomenclature code} and is therefore used for
693
	 * nomenclatural citations. This flag will be set as soon as <i>this</i>
694
	 * reference is used as a nomenclatural reference for any taxon name.<BR>
695
	 * FIXME what happens if the only taxon name referencing this reference is not
696
	 * any longer using this reference as a nomenclatural reference. How does the
697
	 * reference get informed about the fact that it is not nomenclaturally relevant
698
	 * anymore?
699
	 */
700
	public boolean isNomenclaturallyRelevant(){
701
		return this.nomenclaturallyRelevant;
702
	}
703

    
704
	/**
705
	 * @see #isNomenclaturallyRelevant()
706
	 */
707
	public void setNomenclaturallyRelevant(boolean nomenclaturallyRelevant){
708
		this.nomenclaturallyRelevant = nomenclaturallyRelevant;
709
	}
710

    
711

    
712
//****************************************************  /
713

    
714

    
715
	/**
716
	 * Returns a formatted string containing the entire reference citation,
717
	 * including authors, corresponding to <i>this</i> reference.
718
	 *
719
	 * @see  #generateTitle()
720
	 */
721
	// TODO implement
722
	@Transient
723
	public String getCitation(){
724
		rectifyCacheStrategy();
725
		if (getCacheStrategy() == null){
726
			logger.warn("No CacheStrategy defined for "+ this.getClass() + ": " + this.getUuid());
727
			return null;
728
		}else{
729
			return getCacheStrategy().getTitleCache(this);
730
		}
731
	}
732

    
733

    
734
	@Override
735
    public String generateTitle() {
736
		rectifyCacheStrategy();
737
		return super.generateTitle();
738
	}
739

    
740
    public String generateAbbrevTitle() {
741
		rectifyCacheStrategy(); //TODO needed, is called by getCacheStrategy already
742
		return getCacheStrategy().getAbbrevTitleCache(this);
743
	}
744

    
745
	/**
746
	 * Returns a string representation for the year of publication / creation
747
	 * of <i>this</i> reference. If the {@link #getDatePublished() datePublished}
748
	 * of this reference contains more date information then (starting) year
749
	 * only the year is returned.
750
	 * than  attribute.
751
	 */
752
	@Override
753
    @Transient
754
	public String getYear(){
755
		TimePeriod datePublished = this.getDatePublished();
756
		if (datePublished != null ){
757
			String result = getDatePublished().getYear();
758
			return result;
759
		}else{
760
			return null;
761
		}
762
	}
763

    
764
	/**
765
	 * Convenience method that returns a string representation for the publication date / creation
766
	 * of <i>this</i> reference. The string is obtained by
767
	 * {@link #getDatePublished()#toString() the string representation
768
	 * of the date published}.
769
	 */
770
	@Transient
771
	public String getDatePublishedString(){
772
		TimePeriod datePublished = this.getDatePublished();
773
		if (datePublished != null ){
774
			return getDatePublished().toString();
775
		}else{
776
			return null;
777
		}
778
	}
779

    
780

    
781
	@Override
782
    public int getParsingProblem(){
783
		return this.parsingProblem;
784
	}
785

    
786
	@Override
787
    public void setParsingProblem(int parsingProblem){
788
		this.parsingProblem = parsingProblem;
789
	}
790

    
791
	@Override
792
    public boolean hasProblem(){
793
		return parsingProblem != 0;
794
	}
795

    
796
	@Override
797
    public boolean hasProblem(ParserProblem problem) {
798
		return getParsingProblems().contains(problem);
799
	}
800

    
801
	@Override
802
    public int getProblemStarts(){
803
		return this.problemStarts;
804
	}
805

    
806
	@Override
807
    public void setProblemStarts(int start) {
808
		this.problemStarts = start;
809
	}
810

    
811
	@Override
812
    public int getProblemEnds(){
813
		return this.problemEnds;
814
	}
815

    
816
	@Override
817
    public void setProblemEnds(int end) {
818
		this.problemEnds = end;
819
	}
820

    
821
	@Override
822
    public void addParsingProblem(ParserProblem warning){
823
		parsingProblem = ParserProblem.addProblem(parsingProblem, warning);
824
	}
825

    
826
	@Override
827
    public void removeParsingProblem(ParserProblem problem) {
828
		parsingProblem = ParserProblem.removeProblem(parsingProblem, problem);
829
	}
830

    
831
	@Override
832
    @Transient
833
	public List<ParserProblem> getParsingProblems() {
834
		return ParserProblem.warningList(this.parsingProblem);
835
	}
836

    
837

    
838
	@Override
839
    @Transient
840
	public String getNomenclaturalCitation(String microReference) {
841
		rectifyCacheStrategy();
842
		String typeName = this.getType()== null ? "(no type defined)" : this.getType().getMessage();
843
		if (getCacheStrategy() == null){
844
			logger.warn("No CacheStrategy defined for "+ typeName + ": " + this.getUuid());
845
			return null;
846
		}else{
847
			if (getCacheStrategy() instanceof INomenclaturalReferenceCacheStrategy){
848
				return ((INomenclaturalReferenceCacheStrategy)cacheStrategy).getNomenclaturalCitation(this, microReference);
849
			}else {
850
				logger.warn("No INomenclaturalReferenceCacheStrategy defined for "+ typeName + ": " + this.getUuid());
851
				return null;
852
			}
853
		}
854
	}
855

    
856

    
857
	/**
858
	 * Generates, according to the {@link eu.etaxonomy.cdm.strategy.strategy.cache.reference.IReferenceBaseCacheStrategy cache strategy}
859
	 * assigned to <i>this</i> reference, a string that identifies <i>this</i>
860
	 * reference and returns it. This string may be stored in the inherited
861
	 * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} attribute.<BR>
862
	 * This method overrides the generic and inherited generateTitle method
863
	 * from {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity IdentifiableEntity}.
864
	 *
865
	 * @return  the string identifying <i>this</i> reference
866
	 * @see  	#getCitation()
867
	 * @see  	eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache()
868
	 * @see  	eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
869
	 * @see  	eu.etaxonomy.cdm.strategy.strategy.cache.common.IIdentifiableEntityCacheStrategy#getTitleCache()
870
	 */
871
//	@Override
872
//	public String generateTitle(){
873
//		if (cacheStrategy == null){
874
//			logger.warn("No CacheStrategy defined for Reference: " + this.getUuid());
875
//			return null;
876
//		}else{
877
//			return cacheStrategy.getTitleCache(this);
878
//		}
879
//	}
880

    
881

    
882

    
883
//********** Casting methods ***********************************/
884

    
885
	/**
886
	 * @return
887
	 */
888
	public IArticle castReferenceToArticle(){
889
		setType(ReferenceType.Article);
890
		return this;
891
	}
892

    
893
	public IBook castReferenceToBook(){
894
		setType(ReferenceType.Book);
895
		return this;
896
	}
897

    
898
	public IBookSection castReferenceToBookSection(){
899
		setType(ReferenceType.BookSection);
900
		return this;
901
	}
902

    
903
	public ICdDvd castReferenceToCdDvd(){
904
		setType(ReferenceType.CdDvd);
905
		return this;
906
	}
907

    
908
	public IDatabase castReferenceToDatabase(){
909
		setType(ReferenceType.Database);
910
		return this;
911
	}
912

    
913
	public IGeneric castReferenceToGeneric(){
914
		setType(ReferenceType.Generic);
915
		return this;
916
	}
917

    
918
	public IInProceedings castReferenceToInProceedings(){
919
		setType(ReferenceType.InProceedings);
920
		return this;
921
	}
922

    
923
	public IJournal castReferenceToJournal(){
924
		setType(ReferenceType.Journal);
925
		return this;
926
	}
927

    
928
	public IMap castReferenceToMap(){
929
		setType(ReferenceType.Map);
930
		return (IMap) this;
931
	}
932

    
933
	public IPatent castReferenceToPatent(){
934
		setType(ReferenceType.Patent);
935
		return this;
936
	}
937

    
938
	public IPersonalCommunication castReferenceToPersonalCommunication(){
939
		setType(ReferenceType.PersonalCommunication);
940
		return this;
941
	}
942

    
943
	public IPrintSeries castReferenceToPrintSeries(){
944
		setType(ReferenceType.PrintSeries);
945
		return this;
946
	}
947

    
948
	public IWebPage castReferenceToWebPage(){
949
		setType(ReferenceType.WebPage);
950
		return this;
951
	}
952

    
953
	public IProceedings castReferenceToProceedings(){
954
		setType(ReferenceType.Proceedings);
955
		return this;
956
	}
957

    
958
	public IReport castReferenceToReport(){
959
		setType(ReferenceType.Report);
960
		return this;
961
	}
962

    
963
	public IThesis castReferenceToThesis(){
964
		setType(ReferenceType.Thesis);
965
		return this;
966
	}
967

    
968

    
969
	@Override
970
    @Transient // prevent from being serialized by webservice
971
	public IJournal getInJournal() {
972
		IJournal journal = this.inReference;
973
		return journal;
974
	}
975

    
976
	@Override
977
    public void setInJournal(IJournal journal) {
978
		this.inReference = (Reference)journal;
979

    
980
	}
981

    
982
	@Override
983
    @Transient // prevent from being serialized by webservice
984
	public IPrintSeries getInSeries() {
985
		IPrintSeries printSeries = this.inReference;
986
		return printSeries;
987
	}
988

    
989
	@Override
990
    public void setInSeries(IPrintSeries inSeries) {
991
		this.inReference = (Reference) inSeries;
992
	}
993

    
994
	@Override
995
    @Transient // prevent from being serialized by webservice
996
	public IBook getInBook() {
997
		IBook book = this.inReference;
998
		return book;
999
	}
1000

    
1001
//********************** In-References *****************************************
1002

    
1003
	@Override
1004
    public void setInBook(IBook book) {
1005
		this.inReference = (Reference) book;
1006
	}
1007

    
1008
	@Override
1009
    @Transient // prevent from being serialized by webservice
1010
	public IProceedings getInProceedings() {
1011
		IProceedings proceedings = this.inReference;
1012
		return proceedings;
1013
	}
1014

    
1015
	@Override
1016
    public void setInProceedings(IProceedings proceeding) {
1017
		this.inReference = (Reference) proceeding;
1018
	}
1019

    
1020
//*************************** CACHE STRATEGIES ******************************/
1021

    
1022
    @Override
1023
    public IReferenceBaseCacheStrategy getCacheStrategy() {
1024
    	rectifyCacheStrategy();
1025
    	return this.cacheStrategy;
1026
    }
1027

    
1028
	/**
1029
	 * The type property of this class is mapped on the field level to the data base column, so
1030
	 * Hibernate will consequently use the {@link org.hibernate.property.DirectPropertyAccessor}
1031
	 * to set the property. This PropertyAccessor directly sets the field instead of using the according setter so
1032
	 * the CacheStrategy is not correctly set after the initialization of the bean. Thus we need to
1033
	 * validate the CacheStrategy before it is to be used.
1034
	 */
1035
	private void rectifyCacheStrategy() {
1036
		if(!cacheStrategyRectified ){
1037
			setType(getType());
1038
			cacheStrategyRectified = true;
1039
		}
1040
	}
1041

    
1042

    
1043
	@Override
1044
    public void setCacheStrategy(IReferenceBaseCacheStrategy iReferenceBaseCacheStrategy) {
1045
		this.cacheStrategy = iReferenceBaseCacheStrategy;
1046

    
1047
	}
1048

    
1049
	@Override
1050
    public void setCacheStrategy(ArticleDefaultCacheStrategy cacheStrategy) {
1051
		this.cacheStrategy = cacheStrategy;
1052
	}
1053

    
1054
	@Override
1055
    public void setCacheStrategy(BookDefaultCacheStrategy cacheStrategy) {
1056
		this.cacheStrategy = cacheStrategy;
1057
	}
1058

    
1059
	@Override
1060
    public void setCacheStrategy(JournalDefaultCacheStrategy cacheStrategy) {
1061
		this.cacheStrategy = cacheStrategy;
1062
	}
1063

    
1064
	@Override
1065
    public void setCacheStrategy(BookSectionDefaultCacheStrategy cacheStrategy) {
1066
		this.cacheStrategy = cacheStrategy;
1067
	}
1068

    
1069
	@Override
1070
    public void setCacheStrategy(GenericDefaultCacheStrategy cacheStrategy) {
1071
		this.cacheStrategy = cacheStrategy;
1072
	}
1073

    
1074
	public void setCacheStrategy(ReferenceDefaultCacheStrategy cacheStrategy) {
1075
		this.cacheStrategy = cacheStrategy;
1076

    
1077
	}
1078

    
1079

    
1080

    
1081
//    @Override
1082
//    protected void initListener(){
1083
//        PropertyChangeListener listener = new PropertyChangeListener() {
1084
//            @Override
1085
//            public void propertyChange(PropertyChangeEvent e) {
1086
//                boolean protectedByLowerCache = false;
1087
//                //authorship cache
1088
//                if (fieldHasCacheUpdateProperty(e.getPropertyName(), "authorshipCache")){
1089
//                    if (protectedAuthorshipCache){
1090
//                        protectedByLowerCache = true;
1091
//                    }else{
1092
//                        authorshipCache = null;
1093
//                    }
1094
//                }
1095
//
1096
//                //title cache
1097
//                if (! fieldHasNoUpdateProperty(e.getPropertyName(), "titleCache")){
1098
//                    if (isProtectedTitleCache()|| protectedByLowerCache == true ){
1099
//                        protectedByLowerCache = true;
1100
//                    }else{
1101
//                        titleCache = null;
1102
//                    }
1103
//                }
1104
//                //full title cache
1105
//                if (! fieldHasNoUpdateProperty(e.getPropertyName(), "fullTitleCache")){
1106
//                    if (isProtectedFullTitleCache()|| protectedByLowerCache == true ){
1107
//                        protectedByLowerCache = true;
1108
//                    }else{
1109
//                        fullTitleCache = null;
1110
//                    }
1111
//                }
1112
//            }
1113
//        };
1114
//        addPropertyChangeListener(listener);  //didn't use this.addXXX to make lsid.AssemblerTest run in cdmlib-remote
1115
//    }
1116

    
1117

    
1118
//*********************** CLONE ********************************************************/
1119

    
1120
	/**
1121
	 * Clones <i>this</i> reference. This is a shortcut that enables to create
1122
	 * a new instance that differs only slightly from <i>this</i> reference by
1123
	 * modifying only some of the attributes.
1124
	 *
1125
	 * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
1126
	 * @see java.lang.Object#clone()
1127
	 */
1128
	@Override
1129
	public Object clone() {
1130
		try {
1131
			Reference result = (Reference)super.clone();
1132
			result.setDatePublished(datePublished != null? (TimePeriod)datePublished.clone(): null);
1133
			//no changes to: title, authorship, hasProblem, nomenclaturallyRelevant, uri
1134
			return result;
1135
		} catch (CloneNotSupportedException e) {
1136
			logger.warn("Object does not implement cloneable");
1137
			e.printStackTrace();
1138
			return null;
1139
		}
1140
	}
1141

    
1142
//******************************* toString *****************************/
1143

    
1144
	@Override
1145
	public String toString() {
1146
		if (type != null){
1147
			String result = "Reference [type=" + type + ", id= " + this.getId() + ", uuid=" + this.uuid ;
1148
			result += title == null ? "" : ", title=" + title;
1149
			result += abbrevTitle == null ? "" : ", abbrevTitle=" + abbrevTitle;
1150
			result += "]";
1151
			return result;
1152
		}else{
1153
			return super.toString();
1154
		}
1155
	}
1156

    
1157

    
1158

    
1159

    
1160
}
1161

    
(23-23/27)