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
125
        <S extends IReferenceBaseCacheStrategy>
126
        extends IdentifiableMediaEntity<IReferenceBaseCacheStrategy>
127
        implements INomenclaturalReference, IArticle, IBook, IPatent, IDatabase, IJournal, IBookSection,ICdDvd,IGeneric,IInProceedings, IProceedings, IPrintSeries, IReport, IThesis,IWebPage, IPersonalCommunication, IReference, Cloneable {
128

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

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

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

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

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

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

    
172
//********************************************************/
173

    
174

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

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

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

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

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

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

    
218

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

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

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

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

    
248

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

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

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

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

    
281
//********************************************************/
282

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

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

    
297

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

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

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

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

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

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

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

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

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

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

    
365

    
366
//*************************** GETTER / SETTER ******************************************/
367

    
368

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

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

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

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

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

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

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

    
414

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

    
420

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
571
	}
572

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

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

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

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

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

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

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

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

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

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

    
688

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

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

    
712

    
713
//****************************************************  /
714

    
715

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

    
734

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

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

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

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

    
781

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

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

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

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

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

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

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

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

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

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

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

    
838

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

    
857

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

    
882

    
883

    
884
//********** Casting methods ***********************************/
885

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
969

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

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

    
981
	}
982

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

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

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

    
1002
//********************** In-References *****************************************
1003

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

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

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

    
1021
//*************************** CACHE STRATEGIES ******************************/
1022

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

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

    
1043

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

    
1048
	}
1049

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

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

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

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

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

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

    
1078
	}
1079

    
1080

    
1081

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

    
1118

    
1119
//*********************** CLONE ********************************************************/
1120

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

    
1143
//******************************* toString *****************************/
1144

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

    
1158

    
1159

    
1160

    
1161
}
1162

    
(23-23/27)