Project

General

Profile

Download (30.7 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.INomenclaturalReferenceCacheStrategy;
57
import eu.etaxonomy.cdm.strategy.cache.reference.IReferenceCacheStrategy;
58
import eu.etaxonomy.cdm.strategy.cache.reference.NewDefaultReferenceCacheStrategy;
59
import eu.etaxonomy.cdm.strategy.cache.reference.old.ArticleDefaultCacheStrategy;
60
import eu.etaxonomy.cdm.strategy.cache.reference.old.BookDefaultCacheStrategy;
61
import eu.etaxonomy.cdm.strategy.cache.reference.old.BookSectionDefaultCacheStrategy;
62
import eu.etaxonomy.cdm.strategy.cache.reference.old.GenericDefaultCacheStrategy;
63
import eu.etaxonomy.cdm.strategy.cache.reference.old.JournalDefaultCacheStrategy;
64
import eu.etaxonomy.cdm.strategy.cache.reference.old.ReferenceDefaultCacheStrategy;
65
import eu.etaxonomy.cdm.strategy.match.Match;
66
import eu.etaxonomy.cdm.strategy.match.MatchMode;
67
import eu.etaxonomy.cdm.strategy.merge.Merge;
68
import eu.etaxonomy.cdm.strategy.merge.MergeMode;
69
import eu.etaxonomy.cdm.strategy.parser.ParserProblem;
70
import eu.etaxonomy.cdm.validation.Level2;
71
import eu.etaxonomy.cdm.validation.Level3;
72
import eu.etaxonomy.cdm.validation.annotation.InReference;
73
import eu.etaxonomy.cdm.validation.annotation.NoRecursiveInReference;
74
import eu.etaxonomy.cdm.validation.annotation.NullOrNotEmpty;
75
import eu.etaxonomy.cdm.validation.annotation.ReferenceCheck;
76

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

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

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

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

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

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

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

    
173
//********************************************************/
174

    
175

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

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

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

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

    
204
    @XmlElement(name = "ISBN")
205
    @Field
206
    //TODO Val #3379
207
//    @NullOrNotEmpty
208
    @Column(length=255)
209
	@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}")
210
	protected String isbn;
211

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

    
219

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

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

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

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

    
249

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

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

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

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

    
282
//********************************************************/
283

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

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

    
298

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

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

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

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

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

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

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

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

    
340
	protected Reference(ReferenceType type) {
341
		super();
342
	    if (type == null){
343
			this.type = ReferenceType.Generic;
344
		} else{
345
			this.type = type;
346
		}
347
		this.setCacheStrategy(NewDefaultReferenceCacheStrategy.NewInstance());
348
	}
349

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

    
368

    
369
//*************************** GETTER / SETTER ******************************************/
370

    
371

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

    
385
	@Override
386
	@Deprecated
387
	public void setAbbrevTitleCache(String abbrevTitleCache) {
388
		this.abbrevTitleCache = abbrevTitleCache;
389
	}
390

    
391
	@Override
392
	public void setAbbrevTitleCache(String abbrevTitleCache, boolean isProtected) {
393
		this.protectedAbbrevTitleCache = isProtected;
394
		setAbbrevTitleCache(abbrevTitleCache);
395
	}
396

    
397
	@Override
398
	public boolean isProtectedAbbrevTitleCache() {
399
		return protectedAbbrevTitleCache;
400
	}
401

    
402
	@Override
403
	public void setProtectedAbbrevTitleCache(boolean protectedAbbrevTitleCache) {
404
		this.protectedAbbrevTitleCache = protectedAbbrevTitleCache;
405
	}
406

    
407
	@Override
408
	public String getAbbrevTitle() {
409
		return abbrevTitle;
410
	}
411

    
412
	@Override
413
	public void setAbbrevTitle(String abbrevTitle) {
414
		this.abbrevTitle = StringUtils.isBlank(abbrevTitle) ? null : abbrevTitle;
415
	}
416

    
417

    
418
	@Override
419
    public String getEditor() {
420
		return editor;
421
	}
422

    
423

    
424
	@Override
425
    public void setEditor(String editor) {
426
		this.editor = StringUtils.isBlank(editor)? null : editor;
427
	}
428

    
429
	@Override
430
    public String getVolume() {
431
		return volume;
432
	}
433

    
434
	@Override
435
    public void setVolume(String volume) {
436
		this.volume = StringUtils.isBlank(volume)? null : volume;
437
	}
438

    
439
	@Override
440
    public String getPages() {
441
		return pages;
442
	}
443

    
444
	@Override
445
    public void setPages(String pages) {
446
		this.pages = StringUtils.isBlank(pages)? null : pages;
447
	}
448

    
449
	@Override
450
    public String getEdition() {
451
		return edition;
452
	}
453

    
454
	@Override
455
    public void setEdition(String edition) {
456
		this.edition = StringUtils.isBlank(edition)? null : edition;
457
	}
458

    
459
	@Override
460
    public String getIsbn() {
461
		return isbn;
462
	}
463

    
464
	@Override
465
    public void setIsbn(String isbn) {
466
		this.isbn = StringUtils.isBlank(isbn)? null : isbn;
467
	}
468

    
469
	@Override
470
    public String getIssn() {
471
		return issn;
472
	}
473

    
474
	@Override
475
    public void setIssn(String issn) {
476
		this.issn = StringUtils.isBlank(issn)? null : issn;
477
	}
478

    
479
    @Override
480
	public DOI getDoi() {
481
		return doi;
482
	}
483

    
484
    @Override
485
	public void setDoi(DOI doi) {
486
		this.doi = doi;
487
	}
488

    
489
	@Override
490
    public String getSeriesPart() {
491
		return seriesPart;
492
	}
493

    
494
	@Override
495
    public void setSeriesPart(String seriesPart) {
496
		this.seriesPart = StringUtils.isBlank(seriesPart)? null : seriesPart;
497
	}
498

    
499
	@Override
500
    public String getOrganization() {
501
		return organization;
502
	}
503

    
504
	@Override
505
    public void setOrganization(String organization) {
506
		this.organization = StringUtils.isBlank(organization)? null : organization;
507
	}
508

    
509
	@Override
510
    public String getPublisher() {
511
		return publisher;
512
	}
513

    
514
	@Override
515
    public void setPublisher(String publisher) {
516
		this.publisher = StringUtils.isBlank(publisher)? null : publisher;
517
	}
518

    
519
	@Override
520
    public void setPublisher(String publisher, String placePublished){
521
		this.publisher = publisher;
522
		this.placePublished = placePublished;
523
	}
524

    
525
	@Override
526
    public String getPlacePublished() {
527
		return placePublished;
528
	}
529

    
530
	@Override
531
    public void setPlacePublished(String placePublished) {
532
		this.placePublished = StringUtils.isBlank(placePublished)? null: placePublished;
533
	}
534

    
535
	@Override
536
    public Institution getInstitution() {
537
		return institution;
538
	}
539

    
540
	@Override
541
    public void setInstitution(Institution institution) {
542
		this.institution = institution;
543
	}
544

    
545
	@Override
546
    public Institution getSchool() {
547
		return school;
548
	}
549

    
550
	@Override
551
    public void setSchool(Institution school) {
552
		this.school = school;
553
	}
554

    
555
	@Override
556
    public Reference getInReference() {
557
		return inReference;
558
	}
559

    
560
	@Override
561
    public void setInReference(Reference inReference) {
562
		this.inReference = inReference;
563
	}
564

    
565
	@Override
566
    public void setType(ReferenceType type) {
567
		if (type == null){
568
			this.type = ReferenceType.Generic;
569
		} else{
570
			this.type = type;
571
		}
572
		this.setCacheStrategy(type.getCacheStrategy());
573
	}
574
	@Override
575
    public ReferenceType getType() {
576
		return type;
577
	}
578

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

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

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

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

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

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

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

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

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

    
686

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

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

    
710

    
711
//****************************************************  /
712

    
713

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

    
732

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

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

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

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

    
779

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

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

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

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

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

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

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

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

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

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

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

    
836

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

    
855

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

    
880

    
881

    
882
//********** Casting methods ***********************************/
883

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
967

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

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

    
979
	}
980

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

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

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

    
1000
//********************** In-References *****************************************
1001

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

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

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

    
1019
//*************************** CACHE STRATEGIES ******************************/
1020

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

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

    
1041

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

    
1046
	}
1047

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

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

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

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

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

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

    
1076
	}
1077

    
1078

    
1079

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

    
1116

    
1117
//*********************** CLONE ********************************************************/
1118

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

    
1141
//******************************* toString *****************************/
1142

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

    
1156

    
1157

    
1158

    
1159
}
1160

    
(23-23/27)