fix #6449 Add convenience method to set both caches as protected
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / reference / Reference.java
index 4f036582bc1cf7887f1742d54aa3bc7dd2080888..9fceac59a2bdfb811e448a77e9994ed237d0d081 100644 (file)
-/**\r
-* Copyright (C) 2007 EDIT\r
-* European Distributed Institute of Taxonomy\r
-* http://www.e-taxonomy.eu\r
-*\r
-* The contents of this file are subject to the Mozilla Public License Version 1.1\r
-* See LICENSE.TXT at the top of this package for the full license terms.\r
-*/\r
-\r
-package eu.etaxonomy.cdm.model.reference;\r
-\r
-\r
-import java.net.URI;\r
-import java.util.List;\r
-\r
-import javax.persistence.Column;\r
-import javax.persistence.Embedded;\r
-import javax.persistence.Entity;\r
-import javax.persistence.FetchType;\r
-import javax.persistence.Inheritance;\r
-import javax.persistence.InheritanceType;\r
-import javax.persistence.Lob;\r
-import javax.persistence.ManyToOne;\r
-import javax.persistence.Transient;\r
-import javax.validation.constraints.NotNull;\r
-import javax.validation.constraints.Pattern;\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlAttribute;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlIDREF;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-import javax.xml.bind.annotation.XmlSchemaType;\r
-import javax.xml.bind.annotation.XmlType;\r
-\r
-import org.apache.commons.lang.StringUtils;\r
-import org.apache.log4j.Logger;\r
-import org.hibernate.annotations.Cascade;\r
-import org.hibernate.annotations.CascadeType;\r
-import org.hibernate.annotations.Table;\r
-import org.hibernate.annotations.Type;\r
-import org.hibernate.envers.Audited;\r
-import org.hibernate.search.annotations.Analyze;\r
-import org.hibernate.search.annotations.Field;\r
-import org.hibernate.search.annotations.IndexedEmbedded;\r
-import org.hibernate.validator.constraints.Length;\r
-\r
-import eu.etaxonomy.cdm.model.agent.Institution;\r
-import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;\r
-import eu.etaxonomy.cdm.model.common.TimePeriod;\r
-import eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity;\r
-import eu.etaxonomy.cdm.model.name.TaxonNameBase;\r
-import eu.etaxonomy.cdm.strategy.cache.reference.ArticleDefaultCacheStrategy;\r
-import eu.etaxonomy.cdm.strategy.cache.reference.BookDefaultCacheStrategy;\r
-import eu.etaxonomy.cdm.strategy.cache.reference.BookSectionDefaultCacheStrategy;\r
-import eu.etaxonomy.cdm.strategy.cache.reference.GenericDefaultCacheStrategy;\r
-import eu.etaxonomy.cdm.strategy.cache.reference.INomenclaturalReferenceCacheStrategy;\r
-import eu.etaxonomy.cdm.strategy.cache.reference.IReferenceBaseCacheStrategy;\r
-import eu.etaxonomy.cdm.strategy.cache.reference.JournalDefaultCacheStrategy;\r
-import eu.etaxonomy.cdm.strategy.cache.reference.ReferenceDefaultCacheStrategy;\r
-import eu.etaxonomy.cdm.strategy.match.Match;\r
-import eu.etaxonomy.cdm.strategy.match.MatchMode;\r
-import eu.etaxonomy.cdm.strategy.merge.Merge;\r
-import eu.etaxonomy.cdm.strategy.merge.MergeMode;\r
-import eu.etaxonomy.cdm.strategy.parser.ParserProblem;\r
-import eu.etaxonomy.cdm.validation.Level2;\r
-import eu.etaxonomy.cdm.validation.annotation.InReference;\r
-import eu.etaxonomy.cdm.validation.annotation.NullOrNotEmpty;\r
-import eu.etaxonomy.cdm.validation.annotation.ReferenceCheck;\r
-\r
-/**\r
- * The upmost (abstract) class for references (information sources).\r
- * <P>\r
- * This class corresponds to: <ul>\r
- * <li> PublicationCitation according to the TDWG ontology\r
- * <li> Publication according to the TCS\r
- * <li> Reference according to the ABCD schema\r
- * </ul>\r
- *\r
- * @author m.doering\r
- * @created 08-Nov-2007 13:06:47\r
- */\r
-@XmlAccessorType(XmlAccessType.FIELD)\r
-@XmlType(name = "Reference", propOrder = {\r
-       "type",\r
-       "uri",\r
-    "abbrevTitleCache",\r
-    "protectedAbbrevTitleCache",\r
-       "nomenclaturallyRelevant",\r
-    "authorTeam",\r
-    "referenceAbstract",\r
-    "title",\r
-    "abbrevTitle",\r
-    "editor",\r
-       "volume",\r
-       "pages",\r
-       "series",\r
-    "edition",\r
-    "isbn",\r
-    "issn",\r
-    "doi",\r
-    "seriesPart",\r
-    "datePublished",\r
-    "publisher",\r
-    "placePublished",\r
-    "institution",\r
-    "school",\r
-    "organization",\r
-    "inReference"\r
-//    ,"fullReference",\r
-//    "abbreviatedReference"\r
-})\r
-@XmlRootElement(name = "Reference")\r
-@Entity\r
-@Inheritance(strategy=InheritanceType.SINGLE_TABLE)\r
-@Audited\r
-//@javax.persistence.Table(name="Reference")\r
-@Table(appliesTo="Reference", indexes = { @org.hibernate.annotations.Index(name = "ReferenceTitleCacheIndex", columnNames = { "titleCache" }) })\r
-@InReference(groups = Level2.class)\r
-@ReferenceCheck(groups = Level2.class)\r
-//public abstract class Reference<S extends IReferenceBaseCacheStrategy> extends IdentifiableMediaEntity<S> implements IParsable, IMergable, IMatchable, IArticle, IBook, IJournal, IBookSection,ICdDvd,IGeneric,IInProceedings, IProceedings, IPrintSeries, IReport, IThesis,IWebPage {\r
-public class Reference<S extends IReferenceBaseCacheStrategy> extends IdentifiableMediaEntity<S> implements INomenclaturalReference, IArticle, IBook, IPatent, IDatabase, IJournal, IBookSection,ICdDvd,IGeneric,IInProceedings, IProceedings, IPrintSeries, IReport, IThesis,IWebPage, IPersonalCommunication, IReference, Cloneable {\r
-       private static final long serialVersionUID = -2034764545042691295L;\r
-       private static final Logger logger = Logger.getLogger(Reference.class);\r
-\r
-       @XmlAttribute(name ="type")\r
-       @Column(name="refType")\r
-       @NotNull\r
-    @Type(type = "eu.etaxonomy.cdm.hibernate.EnumUserType",\r
-       parameters = {@org.hibernate.annotations.Parameter(name  = "enumClass", value = "eu.etaxonomy.cdm.model.reference.ReferenceType")}\r
-    )\r
-       protected ReferenceType type;\r
-\r
-       //Title of the reference\r
-       @XmlElement(name ="Title" )\r
-       @Column(length=4096, name="title")\r
-       @Lob\r
-       @Field\r
-       @Match(MatchMode.EQUAL_REQUIRED)\r
-    //TODO Val #3379\r
-//     @NullOrNotEmpty\r
-       @Length(max = 4096)  //TODO is the length attribute really requried twice (see @Column)??\r
-       private String title;\r
-       \r
-       //Title of the reference\r
-       @XmlElement(name ="AbbrevTitle" )\r
-       @Field\r
-       @Match(MatchMode.EQUAL)  //TODO check if this is correct\r
-       @NullOrNotEmpty\r
-       @Length(max = 255)\r
-       private String abbrevTitle;\r
-       \r
-       //Title of the reference\r
-       @XmlElement(name ="AbbrevTitleCache" )\r
-       @Field\r
-       @Match(MatchMode.CACHE)\r
-    //TODO Val #3379\r
-//     @NotNull\r
-       @Length(max = 1024)\r
-       private String abbrevTitleCache;\r
-       \r
-       @XmlElement(name = "protectedAbbrevTitleCache")\r
-       @Merge(MergeMode.OR)\r
-       private boolean protectedAbbrevTitleCache;\r
-\r
-//********************************************************/\r
-\r
-\r
-    @XmlElement(name = "Editor")\r
-    @Field\r
-    //TODO Val #3379\r
-//    @NullOrNotEmpty\r
-       @Length(max = 255)\r
-       protected String editor;\r
-\r
-    @XmlElement(name = "Series")\r
-    @Field\r
-    //TODO Val #3379\r
-//    @NullOrNotEmpty\r
-       @Length(max = 255)\r
-       protected String series;\r
-\r
-    @XmlElement(name = "Volume")\r
-    @Field\r
-    //TODO Val #3379\r
-//    @NullOrNotEmpty\r
-       @Length(max = 255)\r
-       protected String volume;\r
-\r
-    @XmlElement(name = "Pages")\r
-    @Field\r
-    //TODO Val #3379\r
-//    @NullOrNotEmpty\r
-       @Length(max = 255)\r
-       protected String pages;\r
-\r
-    @XmlElement(name = "Edition")\r
-    @Field\r
-    //TODO Val #3379\r
-//    @NullOrNotEmpty\r
-       @Length(max = 255)\r
-       protected String edition;\r
-\r
-    @XmlElement(name = "ISBN")\r
-    @Field\r
-    //TODO Val #3379\r
-//    @NullOrNotEmpty\r
-       @Length(max = 255)\r
-       @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}")\r
-       protected String isbn;\r
-\r
-    @XmlElement(name = "Doi")\r
-    @Field\r
-    @NullOrNotEmpty\r
-       @Length(max = 255)\r
-//     @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.doi.message}")\r
-       protected String doi;\r
-\r
-\r
-       @XmlElement(name = "ISSN")\r
-    @Field\r
-    //TODO Val #3379\r
-//     @NullOrNotEmpty\r
-       @Length(max = 255)\r
-       @Pattern(regexp = "(?=.{9}$)\\d{4}([- ])\\d{4} (\\d|X)$", groups = Level2.class, message = "{eu.etaxonomy.cdm.model.reference.Reference.issn.message}")\r
-       protected String issn;\r
-\r
-    @XmlElement(name = "SeriesPart")\r
-    @Field\r
-    //TODO Val #3379\r
-//    @NullOrNotEmpty\r
-       @Length(max = 255)\r
-       protected String seriesPart;\r
-\r
-       @XmlElement(name = "Organization")\r
-    @Field\r
-    //TODO Val #3379\r
-//     @NullOrNotEmpty\r
-       @Length(max = 255)\r
-       protected String organization;\r
-\r
-       @XmlElement(name = "Publisher")\r
-    @Field\r
-    //TODO Val #3379\r
-//     @NullOrNotEmpty\r
-       @Length(max = 255)\r
-       protected String publisher;\r
-\r
-\r
-       @XmlElement(name = "PlacePublished")\r
-    @Field\r
-    //TODO Val #3379\r
-//     @NullOrNotEmpty\r
-       @Length(max = 255)\r
-       protected String placePublished;\r
-\r
-       @XmlElement(name = "Institution")\r
-       @XmlIDREF\r
-       @XmlSchemaType(name = "IDREF")\r
-       @ManyToOne(fetch = FetchType.LAZY)\r
-       @IndexedEmbedded\r
-       @Cascade(CascadeType.SAVE_UPDATE)\r
-       protected Institution institution;\r
-\r
-       @XmlElement(name = "School")\r
-    @XmlIDREF\r
-    @XmlSchemaType(name = "IDREF")\r
-       @ManyToOne(fetch = FetchType.LAZY)\r
-       @IndexedEmbedded\r
-       @Cascade(CascadeType.SAVE_UPDATE)\r
-       protected Institution school;\r
-\r
-    @XmlElement(name = "InReference")\r
-    @XmlIDREF\r
-    @XmlSchemaType(name = "IDREF")\r
-    @ManyToOne(fetch = FetchType.LAZY)\r
-//    @IndexedEmbedded\r
-    @Cascade(CascadeType.SAVE_UPDATE)\r
-   // @InReference(groups=Level2.class)\r
-       protected Reference<?> inReference;\r
-\r
-//    @XmlElement(name = "FullReference")\r
-//    @XmlIDREF\r
-//    @XmlSchemaType(name = "IDREF")\r
-//    @ManyToOne(fetch = FetchType.LAZY)\r
-////    @IndexedEmbedded\r
-//    @Cascade(CascadeType.SAVE_UPDATE)\r
-//    protected Reference fullReference;\r
-//\r
-//    @XmlElement(name = "AbbreviatedReference")\r
-//    @XmlIDREF\r
-//    @XmlSchemaType(name = "IDREF")\r
-//    @ManyToOne(fetch = FetchType.LAZY)\r
-////    @IndexedEmbedded\r
-//    @Cascade(CascadeType.SAVE_UPDATE)\r
-//    protected Reference abbreviatedReference;\r
-\r
-\r
-//********************************************************/\r
-\r
-       //The date range assigned to the reference. ISO Date range like. Flexible, year can be left out, etc\r
-       @XmlElement(name ="DatePublished" )\r
-       @Embedded\r
-       @IndexedEmbedded\r
-       private TimePeriod datePublished = TimePeriod.NewInstance();\r
-\r
-       @XmlElement(name ="Abstract" )\r
-       @Column(length=65536, name="referenceAbstract")\r
-       @Lob\r
-    @Field\r
-    //TODO Val #3379\r
-//     @NullOrNotEmpty\r
-       @Length(max = 65536)\r
-       private String referenceAbstract;  //abstract is a reserved term in Java\r
-\r
-\r
-       //URIs like DOIs, LSIDs or Handles for this reference\r
-       @XmlElement(name = "URI")\r
-       @Field(analyze = Analyze.NO)\r
-       @Type(type="uriUserType")\r
-       private URI uri;\r
-\r
-       //flag to subselect only references that could be useful for nomenclatural citations. If a reference is used as a\r
-       //nomenclatural reference in a name this flag should be automatically set\r
-       @XmlElement(name = "IsNomenclaturallyRelevant")\r
-       @Merge(MergeMode.OR)\r
-       private boolean nomenclaturallyRelevant;\r
-\r
-       @XmlElement(name = "AuthorTeam")\r
-       @XmlIDREF\r
-       @XmlSchemaType(name = "IDREF")\r
-       @ManyToOne(fetch = FetchType.LAZY)\r
-       @IndexedEmbedded\r
-       @Cascade(CascadeType.SAVE_UPDATE)\r
-       private TeamOrPersonBase<?> authorTeam;\r
-\r
-//     @XmlElement(name = "ReferenceIdentity")\r
-//     @XmlIDREF\r
-//     @XmlSchemaType(name = "IDREF")\r
-//     @ManyToOne(fetch = FetchType.LAZY)\r
-//     //@IndexedEmbedded\r
-//     @Cascade(CascadeType.SAVE_UPDATE)\r
-//     @Transient\r
-//     private ReferenceIdentity referenceIdentity;\r
-\r
-       @XmlAttribute\r
-    @Match(MatchMode.IGNORE)\r
-       private int parsingProblem = 0;\r
-\r
-       @XmlAttribute\r
-    @Match(MatchMode.IGNORE)\r
-    private int problemStarts = -1;\r
-\r
-    @XmlAttribute\r
-    @Match(MatchMode.IGNORE)\r
-    private int problemEnds = -1;\r
-\r
-    @Transient\r
-    @XmlAttribute\r
-    @Match(MatchMode.IGNORE)\r
-       private boolean cacheStrategyRectified = false;\r
-\r
-    protected Reference(){\r
-               this(ReferenceType.Generic);\r
-       }\r
-\r
-       protected Reference(ReferenceType type) {\r
-               this.type = type;\r
-               this.cacheStrategy =(S) type.getCacheStrategy();\r
-       }\r
-\r
-\r
-//*************************** GETTER / SETTER ******************************************/\r
-       \r
-\r
-       @Override\r
-       public String getAbbrevTitleCache() {\r
-               if (protectedAbbrevTitleCache){\r
-            return this.abbrevTitleCache;\r
-        }\r
-        // is title dirty, i.e. equal NULL?\r
-        if (abbrevTitleCache == null){\r
-            this.abbrevTitleCache = generateAbbrevTitle();\r
-            this.abbrevTitleCache = getTruncatedCache(this.abbrevTitleCache) ;\r
-        }\r
-        return abbrevTitleCache;       \r
-       }\r
-\r
-       @Override\r
-       @Deprecated\r
-       public void setAbbrevTitleCache(String abbrevTitleCache) {\r
-               this.abbrevTitleCache = abbrevTitleCache;\r
-       }\r
-       \r
-       @Override\r
-       public void setAbbrevTitleCache(String abbrevTitleCache, boolean isProtected) {\r
-               this.protectedAbbrevTitleCache = isProtected;   \r
-               setAbbrevTitleCache(abbrevTitleCache);\r
-       }\r
-       \r
-       @Override\r
-       public boolean isProtectedAbbrevTitleCache() {\r
-               return protectedAbbrevTitleCache;\r
-       }\r
-\r
-       @Override\r
-       public void setProtectedAbbrevTitleCache(boolean protectedAbbrevTitleCache) {\r
-               this.protectedAbbrevTitleCache = protectedAbbrevTitleCache;\r
-       }\r
-\r
-       @Override\r
-       public String getAbbrevTitle() {\r
-               return abbrevTitle;\r
-       }\r
-\r
-       @Override\r
-       public void setAbbrevTitle(String abbrevTitle) {\r
-               this.abbrevTitle = abbrevTitle;\r
-       }\r
-       \r
-\r
-       @Override\r
-    public String getEditor() {\r
-               return editor;\r
-       }\r
-\r
-\r
-       @Override\r
-    public void setEditor(String editor) {\r
-               this.editor = editor;\r
-       }\r
-\r
-       @Override\r
-    public String getSeries() {\r
-               return series;\r
-       }\r
-\r
-       @Override\r
-    public void setSeries(String series) {\r
-               this.series = series;\r
-       }\r
-\r
-       @Override\r
-    public String getVolume() {\r
-               return volume;\r
-       }\r
-\r
-       @Override\r
-    public void setVolume(String volume) {\r
-               this.volume = volume;\r
-       }\r
-\r
-       @Override\r
-    public String getPages() {\r
-               return pages;\r
-       }\r
-\r
-       @Override\r
-    public void setPages(String pages) {\r
-               this.pages = pages;\r
-       }\r
-\r
-       @Override\r
-    public String getEdition() {\r
-               return edition;\r
-       }\r
-\r
-       @Override\r
-    public void setEdition(String edition) {\r
-               this.edition = edition;\r
-       }\r
-\r
-       @Override\r
-    public String getIsbn() {\r
-               return isbn;\r
-       }\r
-\r
-       @Override\r
-    public void setIsbn(String isbn) {\r
-               this.isbn = isbn;\r
-       }\r
-\r
-       @Override\r
-    public String getIssn() {\r
-               return issn;\r
-       }\r
-\r
-       @Override\r
-    public void setIssn(String issn) {\r
-               this.issn = issn;\r
-       }\r
-       \r
-    @Override\r
-       public String getDoi() {\r
-               return doi;\r
-       }\r
-\r
-    @Override\r
-       public void setDoi(String doi) {\r
-               this.doi = doi;\r
-       }\r
-\r
-       @Override\r
-    public String getSeriesPart() {\r
-               return seriesPart;\r
-       }\r
-\r
-       @Override\r
-    public void setSeriesPart(String seriesPart) {\r
-               this.seriesPart = seriesPart;\r
-       }\r
-\r
-       @Override\r
-    public String getOrganization() {\r
-               return organization;\r
-       }\r
-\r
-       @Override\r
-    public void setOrganization(String organization) {\r
-               this.organization = organization;\r
-       }\r
-\r
-       @Override\r
-    public String getPublisher() {\r
-               return publisher;\r
-       }\r
-\r
-       @Override\r
-    public void setPublisher(String publisher) {\r
-               this.publisher = publisher;\r
-       }\r
-\r
-       @Override\r
-    public void setPublisher(String publisher, String placePublished){\r
-               this.publisher = publisher;\r
-               this.placePublished = placePublished;\r
-       }\r
-\r
-       @Override\r
-    public String getPlacePublished() {\r
-               return placePublished;\r
-       }\r
-\r
-       @Override\r
-    public void setPlacePublished(String placePublished) {\r
-               this.placePublished = placePublished;\r
-       }\r
-\r
-       @Override\r
-    public Institution getInstitution() {\r
-               return institution;\r
-       }\r
-\r
-       @Override\r
-    public void setInstitution(Institution institution) {\r
-               this.institution = institution;\r
-       }\r
-\r
-       @Override\r
-    public Institution getSchool() {\r
-               return school;\r
-       }\r
-\r
-       @Override\r
-    public void setSchool(Institution school) {\r
-               this.school = school;\r
-       }\r
-\r
-       @Override\r
-    public Reference getInReference() {\r
-               return inReference;\r
-       }\r
-\r
-       @Override\r
-    public void setInReference(Reference inReference) {\r
-               this.inReference = inReference;\r
-       }\r
-\r
-       @Override\r
-    public void setType(ReferenceType type) {\r
-               this.setCacheStrategy(type.getCacheStrategy());\r
-               this.type = type;\r
-       }\r
-\r
-       /**\r
-        * @return the type\r
-        */\r
-       @Override\r
-    public ReferenceType getType() {\r
-               return type;\r
-       }\r
-\r
-       /**\r
-        * Whether this reference is of the given type\r
-        *\r
-        * @param type\r
-        * @return\r
-        */\r
-       @Override\r
-    public boolean isOfType(ReferenceType type){\r
-               return type == getType();\r
-       }\r
-\r
-       /**\r
-        * Returns a string representing the title of <i>this</i> reference. If a\r
-        * reference has different titles (for instance abbreviated and not\r
-        * abbreviated) then for each title a new instance must be created.\r
-        *\r
-        * @return  the title string of <i>this</i> reference\r
-        * @see         #getCitation()\r
-        */\r
-       @Override\r
-    public String getTitle(){\r
-               return this.title;\r
-       }\r
-       /**\r
-        * @see         #getTitle()\r
-        */\r
-       @Override\r
-    public void setTitle(String title){\r
-               this.title = title;\r
-       }\r
-\r
-       /**\r
-        * Returns the date (mostly only the year) of publication / creation of\r
-        * <i>this</i> reference.\r
-        */\r
-       @Override\r
-    public TimePeriod getDatePublished(){\r
-               return this.datePublished;\r
-       }\r
-       /**\r
-        * @see         #getDatePublished()\r
-        */\r
-       @Override\r
-    public void setDatePublished(TimePeriod datePublished){\r
-               this.datePublished = datePublished;\r
-       }\r
-\r
-       public boolean hasDatePublished(){\r
-               boolean result =  ! ( (this.datePublished == null) || StringUtils.isBlank(datePublished.toString()));\r
-               return result;\r
-       }\r
-\r
-       /**\r
-        * Returns the {@link eu.etaxonomy.cdm.model.agent.TeamOrPersonBase author (team)} who created the\r
-        * content of <i>this</i> reference.\r
-        *\r
-        * @return  the author (team) of <i>this</i> reference\r
-        * @see         eu.etaxonomy.cdm.model.agent.TeamOrPersonBase\r
-        */\r
-       @Override\r
-    public TeamOrPersonBase getAuthorTeam(){\r
-               return this.authorTeam;\r
-       }\r
-\r
-       /**\r
-        * @see #getAuthorTeam()\r
-        */\r
-       @Override\r
-    public void setAuthorTeam(TeamOrPersonBase authorTeam){\r
-               this.authorTeam = authorTeam;\r
-       }\r
-\r
-       /**\r
-        * Returns the Uniform Resource Identifier (URI) corresponding to <i>this</i>\r
-        * reference. An URI is a string of characters used to identify a resource\r
-        * on the Internet.\r
-        *\r
-        * @return  the URI of <i>this</i> reference\r
-        */\r
-       @Override\r
-    public URI getUri(){\r
-               return this.uri;\r
-       }\r
-       /**\r
-        * @see #getUri()\r
-        */\r
-       @Override\r
-    public void setUri(URI uri){\r
-               this.uri = uri;\r
-       }\r
-\r
-       /**\r
-        * @return the referenceAbstract\r
-        */\r
-       @Override\r
-    public String getReferenceAbstract() {\r
-               return referenceAbstract;\r
-       }\r
-\r
-       /**\r
-        * @param referenceAbstract the referenceAbstract to set\r
-        */\r
-       @Override\r
-    public void setReferenceAbstract(String referenceAbstract) {\r
-               this.referenceAbstract = referenceAbstract;\r
-       }\r
-\r
-\r
-\r
-\r
-       /**\r
-        * Returns "true" if the isNomenclaturallyRelevant flag is set. This\r
-        * indicates that a {@link TaxonNameBase taxon name} has been originally\r
-        * published in <i>this</i> reference following the rules of a\r
-        * {@link eu.etaxonomy.cdm.model.name.NomenclaturalCode nomenclature code} and is therefore used for\r
-        * nomenclatural citations. This flag will be set as soon as <i>this</i>\r
-        * reference is used as a nomenclatural reference for any taxon name.<BR>\r
-        * FIXME what happens if the only taxon name referencing this reference is not\r
-        * any longer using this reference as a nomenclatural reference. How does the\r
-        * reference get informed about the fact that it is not nomenclaturally relevant\r
-        * anymore?\r
-        */\r
-       public boolean isNomenclaturallyRelevant(){\r
-               return this.nomenclaturallyRelevant;\r
-       }\r
-\r
-       /**\r
-        * @see #isNomenclaturallyRelevant()\r
-        */\r
-       public void setNomenclaturallyRelevant(boolean nomenclaturallyRelevant){\r
-               this.nomenclaturallyRelevant = nomenclaturallyRelevant;\r
-       }\r
-\r
-\r
-//     /**\r
-//      * Returns the full reference that belongs to this abbreviated reference. If this\r
-//      * reference is not abbreviated the full reference should be <code>null</code>.<BR>\r
-//      * A full reference should be added to a reference\r
-//      * which represents the abbreviated form of a reference. The full reference can be used\r
-//      * by publication tools to link to the unabbreviated and therefore more complete version\r
-//      * of the reference.\r
-//      *\r
-//      * @see #getAbbreviatedReference()\r
-//      * @return the full reference\r
-//      */\r
-//     public Reference getFullReference() {\r
-//             return fullReference;\r
-//     }\r
-//\r
-//     /**\r
-//      * @see #getFullReference()\r
-//      * @param fullReference\r
-//      */\r
-//     public void setFullReference(Reference fullReference) {\r
-//             this.fullReference = fullReference;\r
-//     }\r
-//\r
-//     /**\r
-//      * Returns the abbreviated reference that belongs to this full reference. If this\r
-//      * reference is not a full reference the abbeviated referece must be <code>null</code>.<BR>\r
-//      * An abbreviated reference should be added to a reference which represents the long (full)\r
-//      * form of a reference.\r
-//      * In future this may become a set or handled differently as there are multiple\r
-//      *\r
-//      * @see #getFullReference()\r
-//      * @return the full reference\r
-//      */\r
-//     public Reference getAbbreviatedReference() {\r
-//             return abbreviatedReference;\r
-//     }\r
-//\r
-//     /**\r
-//      * @see #getAbbreviatedReference()\r
-//      * @param abbreviatedReference\r
-//      *\r
-//      */\r
-//     public void setAbbreviatedReference(Reference abbreviatedReference) {\r
-//             this.abbreviatedReference = abbreviatedReference;\r
-//     }\r
-\r
-//****************************************************  /\r
-\r
-//     /**\r
-//      * Returns the string representing the name of the editor of <i>this</i>\r
-//      * generic reference. An editor is mostly a person (team) who assumed the\r
-//      * responsibility for the content of the publication as a whole without\r
-//      * being the author of this content.<BR>\r
-//      * If there is an editor then the generic reference must be some\r
-//      * kind of {@link PrintedUnitBase physical printed unit}.\r
-//      *\r
-//      * @return  the string identifying the editor of <i>this</i>\r
-//      *                      generic reference\r
-//      * @see         #getPublisher()\r
-//      */\r
-//     protected String getEditor(){\r
-//             return this.editor;\r
-//     }\r
-//\r
-//     /**\r
-//      * @see #getEditor()\r
-//      */\r
-//     protected void setEditor(String editor){\r
-//             this.editor = editor;\r
-//     }\r
-//\r
-//     /**\r
-//      * Returns the string representing the series (for instance for books or\r
-//      * within journals) - and series part - in which <i>this</i> generic reference\r
-//      * was published.<BR>\r
-//      * If there is a series then the generic reference must be some\r
-//      * kind of {@link PrintedUnitBase physical printed unit} or an {@link Article article}.\r
-//      *\r
-//      * @return  the string identifying the series for <i>this</i>\r
-//      *                      generic reference\r
-//      */\r
-//     protected String getSeries(){\r
-//             return this.series;\r
-//     }\r
-//\r
-//     /**\r
-//      * @see #getSeries()\r
-//      */\r
-//     protected void setSeries(String series){\r
-//             this.series = series;\r
-//     }\r
-//\r
-//     /**\r
-//      * Returns the string representing the volume (for instance for books or\r
-//      * within journals) in which <i>this</i> generic reference was published.<BR>\r
-//      * If there is a volume then the generic reference must be some\r
-//      * kind of {@link PrintedUnitBase physical printed unit} or an {@link Article article}.\r
-//      *\r
-//      * @return  the string identifying the volume for <i>this</i>\r
-//      *                      generic reference\r
-//      */\r
-//     protected String getVolume(){\r
-//             return this.volume;\r
-//     }\r
-//\r
-//     /**\r
-//      * @see #getVolume()\r
-//      */\r
-//     protected void setVolume(String volume){\r
-//             this.volume = volume;\r
-//     }\r
-//\r
-//     /**\r
-//      * Returns the string representing the page(s) where the content of\r
-//      * <i>this</i> generic reference is located.<BR>\r
-//      * If there is a pages information then the generic reference must be some\r
-//      * kind of {@link PrintedUnitBase physical printed unit} or an {@link Article article}.\r
-//      *\r
-//      * @return  the string containing the pages corresponding to <i>this</i>\r
-//      *                      generic reference\r
-//      */\r
-//     protected String getPages(){\r
-//             return this.pages;\r
-//     }\r
-//\r
-//     /**\r
-//      * @see #getPages()\r
-//      */\r
-//     protected void setPages(String pages){\r
-//             this.pages = pages;\r
-//     }\r
-\r
-\r
-       /**\r
-        * Returns a formatted string containing the entire reference citation,\r
-        * including authors, corresponding to <i>this</i> reference.\r
-        *\r
-        * @see  #generateTitle()\r
-        */\r
-       // TODO implement\r
-       @Transient\r
-       public String getCitation(){\r
-               rectifyCacheStrategy();\r
-               if (cacheStrategy == null){\r
-                       logger.warn("No CacheStrategy defined for "+ this.getClass() + ": " + this.getUuid());\r
-                       return null;\r
-               }else{\r
-                       return cacheStrategy.getTitleCache(this);\r
-               }\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()\r
-        */\r
-       @Override\r
-    public String generateTitle() {\r
-               rectifyCacheStrategy();\r
-               return super.generateTitle();\r
-       }\r
-       \r
-    public String generateAbbrevTitle() {\r
-               rectifyCacheStrategy();\r
-               return this.cacheStrategy.getAbbrevTitleCache(this);\r
-       }\r
-\r
-       /**\r
-        * Returns a string representation for the year of publication / creation\r
-        * of <i>this</i> reference. If the {@link #getDatePublished() datePublished}\r
-        * of this reference contains more date information then (starting) year\r
-        * only the year is returned.\r
-        * than  attribute.\r
-        */\r
-       @Override\r
-    @Transient\r
-       public String getYear(){\r
-               TimePeriod datePublished = this.getDatePublished();\r
-               if (datePublished != null ){\r
-                       String result = getDatePublished().getYear();\r
-                       return result;\r
-               }else{\r
-                       return null;\r
-               }\r
-       }\r
-\r
-       /**\r
-        * Convenience method that returns a string representation for the publication date / creation\r
-        * of <i>this</i> reference. The string is obtained by\r
-        * {@link #getDatePublished()#toString() the string representation\r
-        * of the date published}.\r
-        */\r
-       @Transient\r
-       public String getDatePublishedString(){\r
-               TimePeriod datePublished = this.getDatePublished();\r
-               if (datePublished != null ){\r
-                       return getDatePublished().toString();\r
-               }else{\r
-                       return null;\r
-               }\r
-       }\r
-\r
-\r
-\r
-       /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.model.common.IParsable#getHasProblem()\r
-        */\r
-       @Override\r
-    public int getParsingProblem(){\r
-               return this.parsingProblem;\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.model.common.IParsable#setHasProblem(boolean)\r
-        */\r
-       @Override\r
-    public void setParsingProblem(int parsingProblem){\r
-               this.parsingProblem = parsingProblem;\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.model.common.IParsable#hasProblem()\r
-        */\r
-       @Override\r
-    public boolean hasProblem(){\r
-               return parsingProblem != 0;\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.model.common.IParsable#hasProblem(eu.etaxonomy.cdm.strategy.parser.ParserProblem)\r
-        */\r
-       @Override\r
-    public boolean hasProblem(ParserProblem problem) {\r
-               return getParsingProblems().contains(problem);\r
-       }\r
-\r
-\r
-       /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.model.common.IParsable#problemStarts()\r
-        */\r
-       @Override\r
-    public int getProblemStarts(){\r
-               return this.problemStarts;\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.model.common.IParsable#setProblemStarts(int)\r
-        */\r
-       @Override\r
-    public void setProblemStarts(int start) {\r
-               this.problemStarts = start;\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.model.common.IParsable#problemEnds()\r
-        */\r
-       @Override\r
-    public int getProblemEnds(){\r
-               return this.problemEnds;\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.model.common.IParsable#setProblemEnds(int)\r
-        */\r
-       @Override\r
-    public void setProblemEnds(int end) {\r
-               this.problemEnds = end;\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.model.common.IParsable#addProblem(eu.etaxonomy.cdm.strategy.parser.NameParserWarning)\r
-        */\r
-       @Override\r
-    public void addParsingProblem(ParserProblem warning){\r
-               parsingProblem = ParserProblem.addProblem(parsingProblem, warning);\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.model.common.IParsable#removeParsingProblem(eu.etaxonomy.cdm.strategy.parser.ParserProblem)\r
-        */\r
-       @Override\r
-    public void removeParsingProblem(ParserProblem problem) {\r
-               parsingProblem = ParserProblem.removeProblem(parsingProblem, problem);\r
-       }\r
-\r
-       /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.model.common.IParsable#getParsingProblems()\r
-        */\r
-       @Override\r
-    @Transient\r
-       public List<ParserProblem> getParsingProblems() {\r
-               return ParserProblem.warningList(this.parsingProblem);\r
-       }\r
-\r
-\r
-       @Override\r
-    @Transient\r
-       public String getNomenclaturalCitation(String microReference) {\r
-               rectifyCacheStrategy();\r
-               String typeName = this.getType()== null ? "(no type defined)" : this.getType().getMessage();\r
-               if (cacheStrategy == null){\r
-                       logger.warn("No CacheStrategy defined for "+ typeName + ": " + this.getUuid());\r
-                       return null;\r
-               }else{\r
-                       if (cacheStrategy instanceof INomenclaturalReferenceCacheStrategy){\r
-                               return ((INomenclaturalReferenceCacheStrategy)cacheStrategy).getNomenclaturalCitation(this,microReference);\r
-                       }else {\r
-                               logger.warn("No INomenclaturalReferenceCacheStrategy defined for "+ typeName + ": " + this.getUuid());\r
-                               return null;\r
-                       }\r
-               }\r
-       }\r
-\r
-\r
-       /**\r
-        * Generates, according to the {@link eu.etaxonomy.cdm.strategy.strategy.cache.reference.IReferenceBaseCacheStrategy cache strategy}\r
-        * assigned to <i>this</i> reference, a string that identifies <i>this</i>\r
-        * reference and returns it. This string may be stored in the inherited\r
-        * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} attribute.<BR>\r
-        * This method overrides the generic and inherited generateTitle method\r
-        * from {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity IdentifiableEntity}.\r
-        *\r
-        * @return  the string identifying <i>this</i> reference\r
-        * @see         #getCitation()\r
-        * @see         eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache()\r
-        * @see         eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()\r
-        * @see         eu.etaxonomy.cdm.strategy.strategy.cache.common.IIdentifiableEntityCacheStrategy#getTitleCache()\r
-        */\r
-//     @Override\r
-//     public String generateTitle(){\r
-//             if (cacheStrategy == null){\r
-//                     logger.warn("No CacheStrategy defined for Reference: " + this.getUuid());\r
-//                     return null;\r
-//             }else{\r
-//                     return cacheStrategy.getTitleCache(this);\r
-//             }\r
-//     }\r
-\r
-\r
-\r
-//     /**\r
-//      * Returns the reference identity object\r
-//      * @return the referenceIdentity\r
-//      */\r
-//     public ReferenceIdentity getReferenceIdentity() {\r
-//             return referenceIdentity;\r
-//     }\r
-//\r
-//     /**\r
-//      * For bidirectional use only\r
-//      * @param referenceIdentity the referenceIdentity to set\r
-//      */\r
-//     protected void setReferenceIdentity(ReferenceIdentity referenceIdentity) {\r
-//             this.referenceIdentity = referenceIdentity;\r
-//     }\r
-//\r
-//     /**\r
-//      * Returns the set of all identical references. Same as getReferenceIdentity().getReferences()\r
-//      * @return\r
-//      */\r
-//     public Set<Reference> identicalReferences(){\r
-//             return referenceIdentity.getReferences();\r
-//     }\r
-\r
-\r
-//********** Casting methods ***********************************/\r
-\r
-       public IArticle castReferenceToArticle(){\r
-               setType(ReferenceType.Article);\r
-               return this;\r
-       }\r
-\r
-       public IBook castReferenceToBook(){\r
-               setType(ReferenceType.Book);\r
-               return this;\r
-       }\r
-\r
-       public IBookSection castReferenceToBookSection(){\r
-               setType(ReferenceType.BookSection);\r
-               return this;\r
-       }\r
-\r
-       public ICdDvd castReferenceToCdDvd(){\r
-               setType(ReferenceType.CdDvd);\r
-               return this;\r
-       }\r
-\r
-       public IDatabase castReferenceToDatabase(){\r
-               setType(ReferenceType.Database);\r
-               return this;\r
-       }\r
-\r
-       public IGeneric castReferenceToGeneric(){\r
-               setType(ReferenceType.Generic);\r
-               return this;\r
-       }\r
-\r
-       public IInProceedings castReferenceToInProceedings(){\r
-               setType(ReferenceType.InProceedings);\r
-               return this;\r
-       }\r
-\r
-       public IJournal castReferenceToJournal(){\r
-               setType(ReferenceType.Journal);\r
-               return this;\r
-       }\r
-\r
-       public IMap castReferenceToMap(){\r
-               setType(ReferenceType.Map);\r
-               return (IMap) this;\r
-       }\r
-\r
-       public IPatent castReferenceToPatent(){\r
-               setType(ReferenceType.Patent);\r
-               return this;\r
-       }\r
-\r
-       public IPersonalCommunication castReferenceToPersonalCommunication(){\r
-               setType(ReferenceType.PersonalCommunication);\r
-               return this;\r
-       }\r
-\r
-       public IPrintSeries castReferenceToPrintSeries(){\r
-               setType(ReferenceType.PrintSeries);\r
-               return this;\r
-       }\r
-\r
-       public IWebPage castReferenceToWebPage(){\r
-               setType(ReferenceType.WebPage);\r
-               return this;\r
-       }\r
-\r
-       public IProceedings castReferenceToProceedings(){\r
-               setType(ReferenceType.Proceedings);\r
-               return this;\r
-       }\r
-\r
-       public IReport castReferenceToReport(){\r
-               setType(ReferenceType.Report);\r
-               return this;\r
-       }\r
-\r
-       public IThesis castReferenceToThesis(){\r
-               setType(ReferenceType.Thesis);\r
-               return this;\r
-       }\r
-\r
-\r
-       @Override\r
-    @Transient // prevent from being serialized by webservice\r
-       public IJournal getInJournal() {\r
-               IJournal journal = this.inReference;\r
-               return journal;\r
-       }\r
-\r
-       @Override\r
-    public void setInJournal(IJournal journal) {\r
-               this.inReference = (Reference<JournalDefaultCacheStrategy<Reference>>) journal;\r
-\r
-       }\r
-\r
-       @Override\r
-    @Transient // prevent from being serialized by webservice\r
-       public IPrintSeries getInSeries() {\r
-               IPrintSeries printSeries = this.inReference;\r
-               return printSeries;\r
-       }\r
-\r
-       @Override\r
-    public void setInSeries(IPrintSeries inSeries) {\r
-               this.inReference = (Reference<IReferenceBaseCacheStrategy<Reference>>) inSeries;\r
-       }\r
-\r
-       @Override\r
-    @Transient // prevent from being serialized by webservice\r
-       public IBook getInBook() {\r
-               IBook book = this.inReference;\r
-               return book;\r
-       }\r
-\r
-//********************** In-References *****************************************\r
-\r
-       @Override\r
-    public void setInBook(IBook book) {\r
-               this.inReference = (Reference<BookDefaultCacheStrategy<Reference>>) book;\r
-       }\r
-\r
-       @Override\r
-    @Transient // prevent from being serialized by webservice\r
-       public IProceedings getInProceedings() {\r
-               IProceedings proceedings = this.inReference;\r
-               return proceedings;\r
-       }\r
-\r
-       @Override\r
-    public void setInProceedings(IProceedings proceeding) {\r
-               this.inReference = (Reference<BookDefaultCacheStrategy<Reference>>) proceeding;\r
-       }\r
-\r
-//*************************** CACHE STRATEGIES ******************************/\r
-\r
-       /**\r
-        * The type property of this class is mapped on the field level to the data base column, so\r
-        * Hibernate will consequently use the {@link org.hibernate.property.DirectPropertyAccessor}\r
-        * to set the property. This PropertyAccessor directly sets the field instead of using the according setter so\r
-        * the CacheStrategy is not correctly set after the initialization of the bean. Thus we need to\r
-        * validate the CacheStrategy before it is to be used.\r
-        */\r
-       private void rectifyCacheStrategy() {\r
-               if(!cacheStrategyRectified ){\r
-                       setType(getType());\r
-                       cacheStrategyRectified = true;\r
-               }\r
-       }\r
-\r
-\r
-       //public void setCacheStrategy(S cacheStrategy){\r
-       //      this.cacheStrategy = cacheStrategy;\r
-       //}\r
-\r
-       @Override\r
-    public void setCacheStrategy(IReferenceBaseCacheStrategy iReferenceBaseCacheStrategy) {\r
-               this.cacheStrategy = (S) iReferenceBaseCacheStrategy;\r
-\r
-       }\r
-\r
-       @Override\r
-    public void setCacheStrategy(ArticleDefaultCacheStrategy cacheStrategy) {\r
-               this.cacheStrategy = (S) cacheStrategy;\r
-       }\r
-\r
-       @Override\r
-    public void setCacheStrategy(BookDefaultCacheStrategy cacheStrategy) {\r
-               this.cacheStrategy = (S) cacheStrategy;\r
-       }\r
-\r
-       @Override\r
-    public void setCacheStrategy(JournalDefaultCacheStrategy cacheStrategy) {\r
-               this.cacheStrategy = (S) cacheStrategy;\r
-       }\r
-\r
-       @Override\r
-    public void setCacheStrategy(BookSectionDefaultCacheStrategy cacheStrategy) {\r
-               this.cacheStrategy = (S) cacheStrategy;\r
-       }\r
-\r
-       @Override\r
-    public void setCacheStrategy(GenericDefaultCacheStrategy cacheStrategy) {\r
-               this.cacheStrategy = (S) cacheStrategy;\r
-       }\r
-\r
-       public void setCacheStrategy(ReferenceDefaultCacheStrategy cacheStrategy) {\r
-               this.cacheStrategy = (S)cacheStrategy;\r
-\r
-       }\r
-\r
-\r
-//*********************** CLONE ********************************************************/\r
-\r
-       /**\r
-        * Clones <i>this</i> reference. This is a shortcut that enables to create\r
-        * a new instance that differs only slightly from <i>this</i> reference by\r
-        * modifying only some of the attributes.\r
-        *\r
-        * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()\r
-        * @see java.lang.Object#clone()\r
-        */\r
-       @Override\r
-       public Object clone() {\r
-               try {\r
-                       Reference result = (Reference)super.clone();\r
-                       result.setDatePublished(datePublished != null? (TimePeriod)datePublished.clone(): null);\r
-                       //no changes to: title, authorTeam, hasProblem, nomenclaturallyRelevant, uri\r
-                       return result;\r
-               } catch (CloneNotSupportedException e) {\r
-                       logger.warn("Object does not implement cloneable");\r
-                       e.printStackTrace();\r
-                       return null;\r
-               }\r
-       }\r
-\r
-\r
-}\r
-\r
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.cdm.model.reference;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.net.URI;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.Lob;
+import javax.persistence.ManyToOne;
+import javax.persistence.Transient;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlIDREF;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.hibernate.annotations.Cascade;
+import org.hibernate.annotations.CascadeType;
+import org.hibernate.annotations.Table;
+import org.hibernate.annotations.Type;
+import org.hibernate.envers.Audited;
+import org.hibernate.search.annotations.Analyze;
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.FieldBridge;
+import org.hibernate.search.annotations.IndexedEmbedded;
+
+import eu.etaxonomy.cdm.common.DOI;
+import eu.etaxonomy.cdm.hibernate.search.DoiBridge;
+import eu.etaxonomy.cdm.model.agent.Institution;
+import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
+import eu.etaxonomy.cdm.model.common.IIntextReferenceTarget;
+import eu.etaxonomy.cdm.model.common.TimePeriod;
+import eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity;
+import eu.etaxonomy.cdm.model.name.TaxonNameBase;
+import eu.etaxonomy.cdm.strategy.cache.reference.DefaultReferenceCacheStrategy;
+import eu.etaxonomy.cdm.strategy.cache.reference.INomenclaturalReferenceCacheStrategy;
+import eu.etaxonomy.cdm.strategy.match.Match;
+import eu.etaxonomy.cdm.strategy.match.MatchMode;
+import eu.etaxonomy.cdm.strategy.merge.Merge;
+import eu.etaxonomy.cdm.strategy.merge.MergeMode;
+import eu.etaxonomy.cdm.strategy.parser.ParserProblem;
+import eu.etaxonomy.cdm.validation.Level2;
+import eu.etaxonomy.cdm.validation.Level3;
+import eu.etaxonomy.cdm.validation.annotation.InReference;
+import eu.etaxonomy.cdm.validation.annotation.NoRecursiveInReference;
+import eu.etaxonomy.cdm.validation.annotation.NullOrNotEmpty;
+import eu.etaxonomy.cdm.validation.annotation.ReferenceCheck;
+
+/**
+ * The class for references (information sources). Originally
+ * an abstract class with many subclasses. Not it is only
+ * one class implementing many interfaces for safe use.
+ * <P>
+ * This class corresponds to: <ul>
+ * <li> PublicationCitation according to the TDWG ontology
+ * <li> Publication according to the TCS
+ * <li> Reference according to the ABCD schema
+ * </ul>
+ *
+ * @author m.doering
+ * @created 08-Nov-2007 13:06:47
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "Reference", propOrder = {
+       "type",
+       "uri",
+    "abbrevTitleCache",
+    "protectedAbbrevTitleCache",
+       "nomenclaturallyRelevant",
+    "authorship",
+    "referenceAbstract",
+    "title",
+    "abbrevTitle",
+    "editor",
+       "volume",
+       "pages",
+       "edition",
+    "isbn",
+    "issn",
+    "doi",
+    "seriesPart",
+    "datePublished",
+    "publisher",
+    "placePublished",
+    "institution",
+    "school",
+    "organization",
+    "inReference"
+})
+@XmlRootElement(name = "Reference")
+@Entity
+@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
+@Audited
+@Table(appliesTo="Reference", indexes = { @org.hibernate.annotations.Index(name = "ReferenceTitleCacheIndex", columnNames = { "titleCache" }) })
+//@InReference(groups=Level3.class)
+@ReferenceCheck(groups=Level2.class)
+@InReference(groups=Level3.class)
+@NoRecursiveInReference(groups=Level3.class)  //may become Level1 in future  #
+public class Reference
+        extends IdentifiableMediaEntity<INomenclaturalReferenceCacheStrategy>
+        implements IArticle, IBook, IPatent, IDatabase, IJournal, IBookSection,ICdDvd,
+                   IGeneric,IInProceedings, IProceedings, IPrintSeries, IReport,
+                   IThesis,IWebPage, IPersonalCommunication,
+                   INomenclaturalReference, IReference, IIntextReferenceTarget,
+                   Cloneable {
+
+    private static final long serialVersionUID = -2034764545042691295L;
+       private static final Logger logger = Logger.getLogger(Reference.class);
+
+       @XmlAttribute(name ="type")
+       @Column(name="refType")
+       @NotNull
+    @Type(type = "eu.etaxonomy.cdm.hibernate.EnumUserType",
+       parameters = {@org.hibernate.annotations.Parameter(name  = "enumClass", value = "eu.etaxonomy.cdm.model.reference.ReferenceType")}
+    )
+       @Audited
+       protected ReferenceType type;
+
+       //Title of the reference
+       @XmlElement(name ="Title" )
+       @Column(length=4096, name="title")
+       @Lob
+       @Field
+       @Match(MatchMode.EQUAL_REQUIRED) //TODO correct? was EQUAL_REQUIRED before, but with abbrevTitle this is not realistic anymore
+    //TODO Val #3379
+//     @NullOrNotEmpty
+       private String title;
+
+       //Title of the reference
+       @XmlElement(name ="AbbrevTitle" )
+       @Field
+       @Match(MatchMode.EQUAL)  //TODO check if this is correct
+       @NullOrNotEmpty
+       @Column(length=255)
+       private String abbrevTitle;
+
+       //Title of the reference
+       @XmlElement(name ="AbbrevTitleCache" )
+       @Field
+       @Match(MatchMode.CACHE)
+    //TODO Val #3379
+//     @NotNull
+       @Column(length=1024)
+       private String abbrevTitleCache;
+
+       @XmlElement(name = "protectedAbbrevTitleCache")
+       @Merge(MergeMode.OR)
+       private boolean protectedAbbrevTitleCache;
+
+//********************************************************/
+
+
+    @XmlElement(name = "Editor")
+    @Field
+    //TODO Val #3379
+//    @NullOrNotEmpty
+    @Column(length=255)
+       protected String editor;
+
+    @XmlElement(name = "Volume")
+    @Field
+    //TODO Val #3379
+//    @NullOrNotEmpty
+    @Column(length=255)
+       protected String volume;
+
+    @XmlElement(name = "Pages")
+    @Field
+    //TODO Val #3379
+//    @NullOrNotEmpty
+    @Column(length=255)
+       protected String pages;
+
+    @XmlElement(name = "Edition")
+    @Field
+    //TODO Val #3379
+//    @NullOrNotEmpty
+    @Column(length=255)
+       protected String edition;
+
+    @XmlElement(name = "ISBN")
+    @Field
+    //TODO Val #3379
+//    @NullOrNotEmpty
+    @Column(length=255)
+       @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}")
+       protected String isbn;
+
+    @XmlElement(name = "Doi")
+    @Field
+    @FieldBridge(impl = DoiBridge.class)
+    @Type(type="doiUserType")
+    @Column(length=DOI.MAX_LENGTH)
+    protected DOI doi;
+
+
+       @XmlElement(name = "ISSN")
+    @Field
+    //TODO Val #3379
+//     @NullOrNotEmpty
+    @Column(length=255)
+       @Pattern(regexp = "(?=.{9}$)\\d{4}([- ])\\d{4} (\\d|X)$", groups = Level2.class, message = "{eu.etaxonomy.cdm.model.reference.Reference.issn.message}")
+       protected String issn;
+
+    @XmlElement(name = "SeriesPart")
+    @Field
+    //TODO Val #3379
+//    @NullOrNotEmpty
+    @Column(length=255)
+       protected String seriesPart;
+
+       @XmlElement(name = "Organization")
+    @Field
+    //TODO Val #3379
+//     @NullOrNotEmpty
+    @Column(length=255)
+       protected String organization;
+
+       @XmlElement(name = "Publisher")
+    @Field
+    //TODO Val #3379
+//     @NullOrNotEmpty
+    @Column(length=255)
+       protected String publisher;
+
+
+       @XmlElement(name = "PlacePublished")
+    @Field
+    //TODO Val #3379
+//     @NullOrNotEmpty
+    @Column(length=255)
+       protected String placePublished;
+
+       @XmlElement(name = "Institution")
+       @XmlIDREF
+       @XmlSchemaType(name = "IDREF")
+       @ManyToOne(fetch = FetchType.LAZY)
+       @IndexedEmbedded
+       @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
+       protected Institution institution;
+
+       @XmlElement(name = "School")
+    @XmlIDREF
+    @XmlSchemaType(name = "IDREF")
+       @ManyToOne(fetch = FetchType.LAZY)
+       @IndexedEmbedded
+       @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
+       protected Institution school;
+
+    @XmlElement(name = "InReference")
+    @XmlIDREF
+    @XmlSchemaType(name = "IDREF")
+    @ManyToOne(fetch = FetchType.LAZY)
+//    @IndexedEmbedded
+    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
+   // @InReference(groups=Level2.class)
+       protected Reference inReference;
+
+//********************************************************/
+
+       //The date range assigned to the reference. ISO Date range like. Flexible, year can be left out, etc
+       @XmlElement(name ="DatePublished" )
+       @Embedded
+       @IndexedEmbedded
+       private TimePeriod datePublished = TimePeriod.NewInstance();
+
+       @XmlElement(name ="Abstract" )
+       @Column(length=65536, name="referenceAbstract")
+       @Lob
+    @Field
+    //TODO Val #3379
+//     @NullOrNotEmpty
+       private String referenceAbstract;  //abstract is a reserved term in Java
+
+
+       //URIs like DOIs, LSIDs or Handles for this reference
+       @XmlElement(name = "URI")
+       @Field(analyze = Analyze.NO)
+       @Type(type="uriUserType")
+       private URI uri;
+
+       //flag to subselect only references that could be useful for nomenclatural citations.
+       //If a reference is used as a
+       //nomenclatural reference in a name this flag should be automatically set
+       @XmlElement(name = "IsNomenclaturallyRelevant")
+       @Merge(MergeMode.OR)
+       private boolean nomenclaturallyRelevant;
+
+       @XmlElement(name = "Authorship")
+       @XmlIDREF
+       @XmlSchemaType(name = "IDREF")
+       @ManyToOne(fetch = FetchType.LAZY)
+       @IndexedEmbedded
+       @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
+       private TeamOrPersonBase<?> authorship;
+
+       @XmlAttribute
+    @Match(MatchMode.IGNORE)
+       private int parsingProblem = 0;
+
+       @XmlAttribute
+    @Match(MatchMode.IGNORE)
+    private int problemStarts = -1;
+
+    @XmlAttribute
+    @Match(MatchMode.IGNORE)
+    private int problemEnds = -1;
+
+    @Transient
+    @XmlAttribute
+    @Match(MatchMode.IGNORE)
+       private boolean cacheStrategyRectified = false;
+
+    protected Reference(){
+               this(ReferenceType.Generic);  //just in case someone uses constructor
+       }
+
+       protected Reference(ReferenceType type) {
+               super();
+           if (type == null){
+                       this.type = ReferenceType.Generic;
+               } else{
+                       this.type = type;
+               }
+               this.setCacheStrategy(DefaultReferenceCacheStrategy.NewInstance());
+       }
+
+       @Override
+    public void initListener(){
+        PropertyChangeListener listener = new PropertyChangeListener() {
+            @Override
+            public void propertyChange(PropertyChangeEvent ev) {
+               if (!ev.getPropertyName().equals("titleCache") && !ev.getPropertyName().equals("abbrevTitleCache") && !ev.getPropertyName().equals("cacheStrategy")){
+                       if (! isProtectedTitleCache()){
+                               titleCache = null;
+                       }
+                       if (! isProtectedAbbrevTitleCache()){
+                               abbrevTitleCache = null;
+                       }
+               }
+            }
+        };
+        addPropertyChangeListener(listener);
+    }
+
+
+//*************************** GETTER / SETTER ******************************************/
+
+
+
+    // @Transient  - must not be transient, since this property needs to to be included in all serializations produced by the remote layer
+    @Override
+    public String getTitleCache(){
+        String result = super.getTitleCache();
+        if (isBlank(result)){
+            this.titleCache = this.getAbbrevTitleCache(true);
+        }
+        return titleCache;
+    }
+
+       @Override
+       public String getAbbrevTitleCache() {
+               return getAbbrevTitleCache(false);
+       }
+
+       /**
+        * Implements {@link #getAbbrevTitleCache()} but allows to
+        * avoid never ending recursions if both caches are empty
+        * avoidRecursion should only be <code>true</code> if called
+        * by {@link #getTitleCache()}
+        * @param avoidRecursion
+        * @return
+        */
+       private String getAbbrevTitleCache(boolean avoidRecursion) {
+        if (protectedAbbrevTitleCache){
+            return this.abbrevTitleCache;
+        }
+        // is reference dirty, i.e. equal NULL?
+        if (abbrevTitleCache == null){
+            this.abbrevTitleCache = generateAbbrevTitle();
+            this.abbrevTitleCache = getTruncatedCache(this.abbrevTitleCache) ;
+        }
+        if (isBlank(abbrevTitleCache) && !avoidRecursion){
+            this.abbrevTitleCache = this.getTitleCache();
+        }
+        return abbrevTitleCache;
+    }
+
+
+    @Override
+       @Deprecated
+       public void setAbbrevTitleCache(String abbrevTitleCache) {
+               this.abbrevTitleCache = abbrevTitleCache;
+       }
+
+       @Override
+       public void setAbbrevTitleCache(String abbrevTitleCache, boolean isProtected) {
+               this.protectedAbbrevTitleCache = isProtected;
+               setAbbrevTitleCache(abbrevTitleCache);
+       }
+
+       @Override
+       public boolean isProtectedAbbrevTitleCache() {
+               return protectedAbbrevTitleCache;
+       }
+
+       @Override
+       public void setProtectedAbbrevTitleCache(boolean protectedAbbrevTitleCache) {
+               this.protectedAbbrevTitleCache = protectedAbbrevTitleCache;
+       }
+
+       @Override
+       public String getAbbrevTitle() {
+               return abbrevTitle;
+       }
+
+       @Override
+       public void setAbbrevTitle(String abbrevTitle) {
+               this.abbrevTitle = StringUtils.isBlank(abbrevTitle) ? null : abbrevTitle;
+       }
+
+
+       @Override
+    public String getEditor() {
+               return editor;
+       }
+
+
+       @Override
+    public void setEditor(String editor) {
+               this.editor = StringUtils.isBlank(editor)? null : editor;
+       }
+
+       @Override
+    public String getVolume() {
+               return volume;
+       }
+
+       @Override
+    public void setVolume(String volume) {
+               this.volume = StringUtils.isBlank(volume)? null : volume;
+       }
+
+       @Override
+    public String getPages() {
+               return pages;
+       }
+
+       @Override
+    public void setPages(String pages) {
+               this.pages = StringUtils.isBlank(pages)? null : pages;
+       }
+
+       @Override
+    public String getEdition() {
+               return edition;
+       }
+
+       @Override
+    public void setEdition(String edition) {
+               this.edition = StringUtils.isBlank(edition)? null : edition;
+       }
+
+       @Override
+    public String getIsbn() {
+               return isbn;
+       }
+
+       @Override
+    public void setIsbn(String isbn) {
+               this.isbn = StringUtils.isBlank(isbn)? null : isbn;
+       }
+
+       @Override
+    public String getIssn() {
+               return issn;
+       }
+
+       @Override
+    public void setIssn(String issn) {
+               this.issn = StringUtils.isBlank(issn)? null : issn;
+       }
+
+    @Override
+       public DOI getDoi() {
+               return doi;
+       }
+
+    @Override
+       public void setDoi(DOI doi) {
+               this.doi = doi;
+       }
+
+       @Override
+    public String getSeriesPart() {
+               return seriesPart;
+       }
+
+       @Override
+    public void setSeriesPart(String seriesPart) {
+               this.seriesPart = StringUtils.isBlank(seriesPart)? null : seriesPart;
+       }
+
+       @Override
+    public String getOrganization() {
+               return organization;
+       }
+
+       @Override
+    public void setOrganization(String organization) {
+               this.organization = StringUtils.isBlank(organization)? null : organization;
+       }
+
+       @Override
+    public String getPublisher() {
+               return publisher;
+       }
+
+       @Override
+    public void setPublisher(String publisher) {
+               this.publisher = StringUtils.isBlank(publisher)? null : publisher;
+       }
+
+       @Override
+    public void setPublisher(String publisher, String placePublished){
+               this.publisher = publisher;
+               this.placePublished = placePublished;
+       }
+
+       @Override
+    public String getPlacePublished() {
+               return placePublished;
+       }
+
+       @Override
+    public void setPlacePublished(String placePublished) {
+               this.placePublished = StringUtils.isBlank(placePublished)? null: placePublished;
+       }
+
+       @Override
+    public Institution getInstitution() {
+               return institution;
+       }
+
+       @Override
+    public void setInstitution(Institution institution) {
+               this.institution = institution;
+       }
+
+       @Override
+    public Institution getSchool() {
+               return school;
+       }
+
+       @Override
+    public void setSchool(Institution school) {
+               this.school = school;
+       }
+
+       @Override
+    public Reference getInReference() {
+               return inReference;
+       }
+
+       @Override
+    public void setInReference(Reference inReference) {
+               this.inReference = inReference;
+       }
+
+       @Override
+    public void setType(ReferenceType type) {
+               if (type == null){
+                       this.type = ReferenceType.Generic;
+               } else{
+                       this.type = type;
+               }
+       }
+       @Override
+    public ReferenceType getType() {
+               return type;
+       }
+
+       /**
+        * Whether this reference is of the given type
+        *
+        * @param type
+        * @return
+        */
+       @Override
+    public boolean isOfType(ReferenceType type){
+               return type == getType();
+       }
+
+       /**
+        * Returns a string representing the title of <i>this</i> reference. If a
+        * reference has different titles (for instance abbreviated and not
+        * abbreviated) then for each title a new instance must be created.
+        *
+        * @return  the title string of <i>this</i> reference
+        * @see         #getCitation()
+        */
+       @Override
+    public String getTitle(){
+               return this.title;
+       }
+       /**
+        * @see         #getTitle()
+        */
+       @Override
+    public void setTitle(String title){
+               this.title = StringUtils.isBlank(title)? null : title;
+       }
+
+       /**
+        * Returns the date (mostly only the year) of publication / creation of
+        * <i>this</i> reference.
+        */
+       @Override
+    public TimePeriod getDatePublished(){
+               return this.datePublished;
+       }
+       /**
+        * @see         #getDatePublished()
+        */
+       @Override
+    public void setDatePublished(TimePeriod datePublished){
+               this.datePublished = datePublished;
+       }
+
+       public boolean hasDatePublished(){
+               boolean result =  ! ( (this.datePublished == null) || StringUtils.isBlank(datePublished.toString()));
+               return result;
+       }
+
+       /**
+        * Returns the {@link eu.etaxonomy.cdm.model.agent.TeamOrPersonBase author (team)} who created the
+        * content of <i>this</i> reference.
+        *
+        * @return  the author (team) of <i>this</i> reference
+        * @see         eu.etaxonomy.cdm.model.agent.TeamOrPersonBase
+        */
+       @Override
+    public TeamOrPersonBase getAuthorship(){
+               return this.authorship;
+       }
+
+       /**
+        * @see #getAuthorship()
+        */
+       @Override
+    public void setAuthorship(TeamOrPersonBase authorship){
+               this.authorship = authorship;
+       }
+
+       /**
+        * Returns the Uniform Resource Identifier (URI) corresponding to <i>this</i>
+        * reference. An URI is a string of characters used to identify a resource
+        * on the Internet.
+        *
+        * @return  the URI of <i>this</i> reference
+        */
+       @Override
+    public URI getUri(){
+               return this.uri;
+       }
+       /**
+        * @see #getUri()
+        */
+       @Override
+    public void setUri(URI uri){
+               this.uri = uri;
+       }
+
+       /**
+        * @return the referenceAbstract
+        */
+       @Override
+    public String getReferenceAbstract() {
+               return referenceAbstract;
+       }
+
+       /**
+        * @param referenceAbstract the referenceAbstract to set
+        */
+       @Override
+    public void setReferenceAbstract(String referenceAbstract) {
+               this.referenceAbstract = StringUtils.isBlank(referenceAbstract)? null : referenceAbstract;
+       }
+
+
+       /**
+        * Returns "true" if the isNomenclaturallyRelevant flag is set. This
+        * indicates that a {@link TaxonNameBase taxon name} has been originally
+        * published in <i>this</i> reference following the rules of a
+        * {@link eu.etaxonomy.cdm.model.name.NomenclaturalCode nomenclature code} and is therefore used for
+        * nomenclatural citations. This flag will be set as soon as <i>this</i>
+        * reference is used as a nomenclatural reference for any taxon name.<BR>
+        * FIXME what happens if the only taxon name referencing this reference is not
+        * any longer using this reference as a nomenclatural reference. How does the
+        * reference get informed about the fact that it is not nomenclaturally relevant
+        * anymore?
+        */
+       public boolean isNomenclaturallyRelevant(){
+               return this.nomenclaturallyRelevant;
+       }
+
+       /**
+        * @see #isNomenclaturallyRelevant()
+        */
+       public void setNomenclaturallyRelevant(boolean nomenclaturallyRelevant){
+               this.nomenclaturallyRelevant = nomenclaturallyRelevant;
+       }
+
+
+//****************************************************  /
+
+       @Transient
+       @Override
+       public void setTitleCaches(String cache){
+           this.setAbbrevTitleCache(cache, true);
+           this.setTitleCache(cache, true);
+       }
+
+
+       /**
+        * Returns a formatted string containing the entire reference citation,
+        * including authors, corresponding to <i>this</i> reference.
+        *
+        * @see  #generateTitle()
+        */
+       // TODO implement
+       @Transient
+       public String getCitation(){
+               if (getCacheStrategy() == null){
+                       logger.warn("No CacheStrategy defined for "+ this.getClass() + ": " + this.getUuid());
+                       return null;
+               }else{
+                       return getCacheStrategy().getTitleCache(this);
+               }
+       }
+
+
+       @Override
+    public String generateTitle() {
+               return super.generateTitle();
+       }
+
+    public String generateAbbrevTitle() {
+               return getCacheStrategy().getFullAbbrevTitleString(this);
+       }
+
+       /**
+        * Returns a string representation for the year of publication / creation
+        * of <i>this</i> reference. If the {@link #getDatePublished() datePublished}
+        * of this reference contains more date information then (starting) year
+        * only the year is returned.
+        * than  attribute.
+        */
+       @Override
+    @Transient
+       public String getYear(){
+               TimePeriod datePublished = this.getDatePublished();
+               if (datePublished != null ){
+                       String result = getDatePublished().getYear();
+                       return result;
+               }else{
+                       return null;
+               }
+       }
+
+       /**
+        * Convenience method that returns a string representation for the publication date / creation
+        * of <i>this</i> reference. The string is obtained by
+        * {@link #getDatePublished()#toString() the string representation
+        * of the date published}.
+        */
+       @Transient
+       public String getDatePublishedString(){
+               TimePeriod datePublished = this.getDatePublished();
+               if (datePublished != null ){
+                       return getDatePublished().toString();
+               }else{
+                       return null;
+               }
+       }
+
+
+       @Override
+    public int getParsingProblem(){
+               return this.parsingProblem;
+       }
+
+       @Override
+    public void setParsingProblem(int parsingProblem){
+               this.parsingProblem = parsingProblem;
+       }
+
+       @Override
+    public boolean hasProblem(){
+               return parsingProblem != 0;
+       }
+
+       @Override
+    public boolean hasProblem(ParserProblem problem) {
+               return getParsingProblems().contains(problem);
+       }
+
+       @Override
+    public int getProblemStarts(){
+               return this.problemStarts;
+       }
+
+       @Override
+    public void setProblemStarts(int start) {
+               this.problemStarts = start;
+       }
+
+       @Override
+    public int getProblemEnds(){
+               return this.problemEnds;
+       }
+
+       @Override
+    public void setProblemEnds(int end) {
+               this.problemEnds = end;
+       }
+
+       @Override
+    public void addParsingProblem(ParserProblem warning){
+               parsingProblem = ParserProblem.addProblem(parsingProblem, warning);
+       }
+
+       @Override
+    public void removeParsingProblem(ParserProblem problem) {
+               parsingProblem = ParserProblem.removeProblem(parsingProblem, problem);
+       }
+
+       @Override
+    @Transient
+       public List<ParserProblem> getParsingProblems() {
+               return ParserProblem.warningList(this.parsingProblem);
+       }
+
+
+       @Override
+    @Transient
+    public String getNomenclaturalCitation(String microReference) {
+               String typeName = this.getType()== null ? "(no type defined)" : this.getType().getMessage();
+               if (getCacheStrategy() == null){
+                       logger.warn("No CacheStrategy defined for "+ typeName + ": " + this.getUuid());
+                       return null;
+               }else{
+                   if (getCacheStrategy() instanceof INomenclaturalReferenceCacheStrategy){
+                               return cacheStrategy.getNomenclaturalCitation(this, microReference);
+                       }else {
+                               logger.warn("No INomenclaturalReferenceCacheStrategy defined for "+ typeName + ": " + this.getUuid());
+                               return null;
+                       }
+               }
+       }
+
+
+       /**
+        * Generates, according to the {@link eu.etaxonomy.cdm.strategy.strategy.cache.reference.IReferenceBaseCacheStrategy cache strategy}
+        * assigned to <i>this</i> reference, a string that identifies <i>this</i>
+        * reference and returns it. This string may be stored in the inherited
+        * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} attribute.<BR>
+        * This method overrides the generic and inherited generateTitle method
+        * from {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity IdentifiableEntity}.
+        *
+        * @return  the string identifying <i>this</i> reference
+        * @see         #getCitation()
+        * @see         eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache()
+        * @see         eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
+        * @see         eu.etaxonomy.cdm.strategy.strategy.cache.common.IIdentifiableEntityCacheStrategy#getTitleCache()
+        */
+//     @Override
+//     public String generateTitle(){
+//             if (cacheStrategy == null){
+//                     logger.warn("No CacheStrategy defined for Reference: " + this.getUuid());
+//                     return null;
+//             }else{
+//                     return cacheStrategy.getTitleCache(this);
+//             }
+//     }
+
+
+
+//********** Casting methods ***********************************/
+
+       /**
+        * @return
+        */
+       public IArticle castReferenceToArticle(){
+               setType(ReferenceType.Article);
+               return this;
+       }
+
+       public IBook castReferenceToBook(){
+               setType(ReferenceType.Book);
+               return this;
+       }
+
+       public IBookSection castReferenceToBookSection(){
+               setType(ReferenceType.BookSection);
+               return this;
+       }
+
+       public ICdDvd castReferenceToCdDvd(){
+               setType(ReferenceType.CdDvd);
+               return this;
+       }
+
+       public IDatabase castReferenceToDatabase(){
+               setType(ReferenceType.Database);
+               return this;
+       }
+
+       public IGeneric castReferenceToGeneric(){
+               setType(ReferenceType.Generic);
+               return this;
+       }
+
+       public IInProceedings castReferenceToInProceedings(){
+               setType(ReferenceType.InProceedings);
+               return this;
+       }
+
+       public IJournal castReferenceToJournal(){
+               setType(ReferenceType.Journal);
+               return this;
+       }
+
+       public IMap castReferenceToMap(){
+               setType(ReferenceType.Map);
+               return (IMap) this;
+       }
+
+       public IPatent castReferenceToPatent(){
+               setType(ReferenceType.Patent);
+               return this;
+       }
+
+       public IPersonalCommunication castReferenceToPersonalCommunication(){
+               setType(ReferenceType.PersonalCommunication);
+               return this;
+       }
+
+       public IPrintSeries castReferenceToPrintSeries(){
+               setType(ReferenceType.PrintSeries);
+               return this;
+       }
+
+       public IWebPage castReferenceToWebPage(){
+               setType(ReferenceType.WebPage);
+               return this;
+       }
+
+       public IProceedings castReferenceToProceedings(){
+               setType(ReferenceType.Proceedings);
+               return this;
+       }
+
+       public IReport castReferenceToReport(){
+               setType(ReferenceType.Report);
+               return this;
+       }
+
+       public IThesis castReferenceToThesis(){
+               setType(ReferenceType.Thesis);
+               return this;
+       }
+
+
+       @Override
+    @Transient // prevent from being serialized by webservice
+       public IJournal getInJournal() {
+               IJournal journal = this.inReference;
+               return journal;
+       }
+
+       @Override
+    public void setInJournal(IJournal journal) {
+               setInReference((Reference)journal);  //user setter to invoke aspect #1815
+       }
+
+       @Override
+    @Transient // prevent from being serialized by webservice
+       public IPrintSeries getInSeries() {
+               return this.inReference;
+       }
+
+       @Override
+    public void setInSeries(IPrintSeries inSeries) {
+           setInReference((Reference)inSeries);  //user setter to invoke aspect  #1815
+       }
+
+       @Override
+    @Transient // prevent from being serialized by webservice
+       public IBook getInBook() {
+               IBook book = this.inReference;
+               return book;
+       }
+
+//********************** In-References *****************************************
+
+       @Override
+    public void setInBook(IBook book) {
+           setInReference((Reference)book);  //user setter to invoke aspect #1815
+       }
+
+       @Override
+    @Transient // prevent from being serialized by webservice
+       public IProceedings getInProceedings() {
+               IProceedings proceedings = this.inReference;
+               return proceedings;
+       }
+
+       @Override
+    public void setInProceedings(IProceedings proceeding) {
+        setInReference((Reference)proceeding);  //user setter to invoke aspect #1815
+       }
+
+//*************************** CACHE STRATEGIES ******************************/
+
+    @Override
+    public INomenclaturalReferenceCacheStrategy getCacheStrategy() {
+       return this.cacheStrategy;
+    }
+
+       @Override
+    public void setCacheStrategy(INomenclaturalReferenceCacheStrategy referenceCacheStrategy) {
+               this.cacheStrategy = referenceCacheStrategy;
+       }
+
+
+
+//*********************** CLONE ********************************************************/
+
+       /**
+        * Clones <i>this</i> reference. This is a shortcut that enables to create
+        * a new instance that differs only slightly from <i>this</i> reference by
+        * modifying only some of the attributes.
+        *
+        * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
+        * @see java.lang.Object#clone()
+        */
+       @Override
+       public Object clone() {
+               try {
+                       Reference result = (Reference)super.clone();
+                       result.setDatePublished(datePublished != null? (TimePeriod)datePublished.clone(): null);
+                       //no changes to: title, authorship, hasProblem, nomenclaturallyRelevant, uri
+                       return result;
+               } catch (CloneNotSupportedException e) {
+                       logger.warn("Object does not implement cloneable");
+                       e.printStackTrace();
+                       return null;
+               }
+       }
+
+//******************************* toString *****************************/
+
+       @Override
+       public String toString() {
+               if (type != null){
+                       String result = "Reference [type=" + type + ", id= " + this.getId() + ", uuid=" + this.uuid ;
+                       result += title == null ? "" : ", title=" + title;
+                       result += abbrevTitle == null ? "" : ", abbrevTitle=" + abbrevTitle;
+                       result += "]";
+                       return result;
+               }else{
+                       return super.toString();
+               }
+       }
+
+
+
+
+}
+