cleanup
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / reference / Reference.java
index 7f389ee9034db73f9368ef3b5d78c52a75eeba60..673ddf17aa35a30fa4b53c355520b2204be6db6f 100644 (file)
@@ -11,7 +11,6 @@ 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.Basic;
@@ -38,10 +37,12 @@ import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 
-import org.apache.commons.lang.StringUtils;
-import org.apache.log4j.Logger;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 import org.hibernate.annotations.Cascade;
 import org.hibernate.annotations.CascadeType;
+import org.hibernate.annotations.Parameter;
 import org.hibernate.annotations.Type;
 import org.hibernate.envers.Audited;
 import org.hibernate.search.annotations.Analyze;
@@ -49,20 +50,26 @@ import org.hibernate.search.annotations.Field;
 import org.hibernate.search.annotations.FieldBridge;
 import org.hibernate.search.annotations.IndexedEmbedded;
 import org.joda.time.DateTime;
+import org.joda.time.Partial;
 
 import eu.etaxonomy.cdm.common.DOI;
+import eu.etaxonomy.cdm.common.URI;
+import eu.etaxonomy.cdm.format.common.TimePeriodPartialFormatter;
+import eu.etaxonomy.cdm.format.reference.NomenclaturalSourceFormatter;
 import eu.etaxonomy.cdm.hibernate.search.DateTimeBridge;
 import eu.etaxonomy.cdm.hibernate.search.DoiBridge;
+import eu.etaxonomy.cdm.hibernate.search.UriBridge;
 import eu.etaxonomy.cdm.jaxb.DateTimeAdapter;
 import eu.etaxonomy.cdm.model.agent.Institution;
 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
+import eu.etaxonomy.cdm.model.common.ExternallyManaged;
 import eu.etaxonomy.cdm.model.common.IIntextReferenceTarget;
 import eu.etaxonomy.cdm.model.common.TimePeriod;
 import eu.etaxonomy.cdm.model.common.VerbatimTimePeriod;
 import eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity;
 import eu.etaxonomy.cdm.model.name.TaxonName;
-import eu.etaxonomy.cdm.strategy.cache.reference.DefaultReferenceCacheStrategy;
-import eu.etaxonomy.cdm.strategy.cache.reference.INomenclaturalReferenceCacheStrategy;
+import eu.etaxonomy.cdm.strategy.cache.reference.IReferenceCacheStrategy;
+import eu.etaxonomy.cdm.strategy.cache.reference.ReferenceDefaultCacheStrategy;
 import eu.etaxonomy.cdm.strategy.match.Match;
 import eu.etaxonomy.cdm.strategy.match.MatchMode;
 import eu.etaxonomy.cdm.strategy.merge.Merge;
@@ -77,8 +84,14 @@ 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.
+ * an abstract class with many subclasses. Now it is only
+ * one class implementing many interfaces for safe use of different
+ * types of references. E.g. if you want to edit a journal
+ * you create a journal with {@link ReferenceFactory#newJournal()}
+ * which returns an IJournal. Though this instance is an ordinary instance
+ * of {@link Reference} by using IJournal you may not use attributes
+ * not allowed for journals.<p>
+ * References can be created via {@link ReferenceFactory} methods.
  * <P>
  * This class corresponds to: <ul>
  * <li> PublicationCitation according to the TDWG ontology
@@ -110,52 +123,57 @@ import eu.etaxonomy.cdm.validation.annotation.ReferenceCheck;
     "seriesPart",
     "datePublished",
     "publisher",
+    "publisher2",
     "placePublished",
+    "placePublished2",
     "institution",
     "school",
     "organization",
     "inReference",
     "accessed",
-    "lastRetrieved",
-    "externalId",
-    "externalLink",
-    "authorityType"
+    "externallyManaged",
 })
 @XmlRootElement(name = "Reference")
 @Entity
 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
 @Audited
-@Table(name="Reference", indexes = { @javax.persistence.Index(name = "ReferenceTitleCacheIndex", columnList = "titleCache") })
+@Table(name="Reference", indexes = { @javax.persistence.Index(name = "referenceTitleCacheIndex", columnList = "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>
+        extends IdentifiableMediaEntity<IReferenceCacheStrategy>
         implements IArticle, IBook, IPatent, IDatabase, IJournal, IBookSection,ICdDvd,
                    IGeneric,IInProceedings, IProceedings, IPrintSeries, IReport,
                    IThesis,IWebPage, IPersonalCommunication,
-                   INomenclaturalReference, IReference, IIntextReferenceTarget,
-                   Cloneable {
+                   IIntextReferenceTarget {
 
     private static final long serialVersionUID = -2034764545042691295L;
-       private static final Logger logger = Logger.getLogger(Reference.class);
+       private static final Logger logger = LogManager.getLogger();
 
-       @XmlAttribute(name ="type")
+//  from E+M import (still needed?)
+//     @Column(length=255)
+//  private String refAuthorString;
+//     public String getRefAuthorString() {return refAuthorString;}
+//  public void setRefAuthorString(String refAuthorString) {this.refAuthorString = refAuthorString;}
+
+    @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")}
+       parameters = {@Parameter(name  = "enumClass",
+       value = "eu.etaxonomy.cdm.model.reference.ReferenceType")}
     )
        @Audited
-       protected ReferenceType type;
+       private 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
+       @Match(MatchMode.EQUAL_REQUIRED) //TODO correct? was EQUAL_REQUIRED before, but with abbrevTitle this is not realistic anymore, see also #6427
     //TODO Val #3379
 //     @NullOrNotEmpty
        private String title;
@@ -183,34 +201,33 @@ public class Reference
 
 //********************************************************/
 
-
     @XmlElement(name = "Editor")
     @Field
     //TODO Val #3379
 //    @NullOrNotEmpty
     @Column(length=255)
-       protected String editor;
+    private String editor;
 
     @XmlElement(name = "Volume")
     @Field
     //TODO Val #3379
 //    @NullOrNotEmpty
     @Column(length=255)
-       protected String volume;
+    private String volume;
 
     @XmlElement(name = "Pages")
     @Field
     //TODO Val #3379
 //    @NullOrNotEmpty
     @Column(length=255)
-       protected String pages;
+    private String pages;
 
     @XmlElement(name = "Edition")
     @Field
     //TODO Val #3379
 //    @NullOrNotEmpty
     @Column(length=255)
-       protected String edition;
+    private String edition;
 
     @XmlElement(name = "ISBN")
     @Field
@@ -218,15 +235,14 @@ public class Reference
 //    @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;
+    private String isbn;
 
     @XmlElement(name = "Doi")
     @Field
     @FieldBridge(impl = DoiBridge.class)
     @Type(type="doiUserType")
     @Column(length=DOI.MAX_LENGTH)
-    protected DOI doi;
-
+    private DOI doi;
 
        @XmlElement(name = "ISSN")
     @Field
@@ -234,36 +250,45 @@ public class Reference
 //     @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;
+       private String issn;
 
     @XmlElement(name = "SeriesPart")
     @Field
     //TODO Val #3379
 //    @NullOrNotEmpty
     @Column(length=255)
-       protected String seriesPart;
+    private String seriesPart;
 
        @XmlElement(name = "Organization")
     @Field
     //TODO Val #3379
 //     @NullOrNotEmpty
     @Column(length=255)
-       protected String organization;
+       private String organization;
 
        @XmlElement(name = "Publisher")
     @Field
     //TODO Val #3379
 //     @NullOrNotEmpty
     @Column(length=255)
-       protected String publisher;
+       private String publisher;
 
+    @XmlElement(name = "Publisher2")
+    @Field
+    @Column(length=255)
+    private String publisher2;
 
        @XmlElement(name = "PlacePublished")
     @Field
     //TODO Val #3379
 //     @NullOrNotEmpty
     @Column(length=255)
-       protected String placePublished;
+       private String placePublished;
+
+    @XmlElement(name = "PlacePublished2")
+    @Field
+    @Column(length=255)
+    private String placePublished2;
 
        @XmlElement(name = "Institution")
        @XmlIDREF
@@ -271,7 +296,7 @@ public class Reference
        @ManyToOne(fetch = FetchType.LAZY)
        @IndexedEmbedded
        @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
-       protected Institution institution;
+       private Institution institution;
 
        @XmlElement(name = "School")
     @XmlIDREF
@@ -279,7 +304,7 @@ public class Reference
        @ManyToOne(fetch = FetchType.LAZY)
        @IndexedEmbedded
        @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
-       protected Institution school;
+       private Institution school;
 
     @XmlElement(name = "InReference")
     @XmlIDREF
@@ -287,7 +312,7 @@ public class Reference
     @ManyToOne(fetch = FetchType.LAZY)
     @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
 //  @InReference(groups=Level2.class)
-       protected Reference inReference;
+    private Reference inReference;
 
 //********************************************************/
 
@@ -307,7 +332,7 @@ public class Reference
     private DateTime accessed;
 
     @XmlElement(name ="Abstract" )
-       @Column(length=65536, name="referenceAbstract")
+       @Column(length=CLOB_LENGTH, name="referenceAbstract")
        @Lob
     @Field
     //TODO Val #3379
@@ -318,6 +343,7 @@ public class Reference
        //URIs like DOIs, LSIDs or Handles for this reference
        @XmlElement(name = "URI")
        @Field(analyze = Analyze.NO)
+    @FieldBridge(impl = UriBridge.class)
        @Type(type="uriUserType")
        private URI uri;
 
@@ -337,6 +363,8 @@ public class Reference
        @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
        private TeamOrPersonBase<?> authorship;
 
+    private ExternallyManaged externallyManaged;
+
        @XmlAttribute
     @Match(MatchMode.IGNORE)
        private int parsingProblem = 0;
@@ -349,43 +377,12 @@ public class Reference
     @Match(MatchMode.IGNORE)
     private int problemEnds = -1;
 
-    @Transient
-    @XmlAttribute
-    @Match(MatchMode.IGNORE)
-       private boolean cacheStrategyRectified = false;
-
-    //attributes for externally managed
-
-//    @XmlElement (name = "LastRetrieved", type= String.class)
-    @XmlJavaTypeAdapter(DateTimeAdapter.class)
-    @Type(type="dateTimeUserType")
-    //TODO needed??
-    @Basic(fetch = FetchType.LAZY)
-    private DateTime lastRetrieved;
-
-    @XmlElement(name ="ExternalId" )
-//    @Field
-//    @Match(MatchMode.EQUAL)  //TODO check if this is correct
-    @NullOrNotEmpty
-    @Column(length=255)
-    private String externalId;
-
-    //Actionable link on e.g. on a webservice
-    @XmlElement(name = "ExternalLink")
-    @Field(analyze = Analyze.NO)
-    @Type(type="uriUserType")
-    private URI externalLink;
-
-    @XmlAttribute(name ="authority")
-    @Column(name="authorityType", length=10)
-    @Type(type = "eu.etaxonomy.cdm.hibernate.EnumUserType",
-        parameters = {@org.hibernate.annotations.Parameter(name  = "enumClass", value = "eu.etaxonomy.cdm.model.reference.AuthorityType")}
-    )
-//    @NotNull
-    private AuthorityType authorityType;
 
 // *********************** CONSTRUCTOR ************************/
 
+    //for hibernate use only, *packet* private required by bytebuddy
+    //TODO currenctly still protected as OpenUrlReference inherits from Reference
+    //     this should be fixed
     protected Reference(){
                this(ReferenceType.Generic);  //just in case someone uses constructor
        }
@@ -397,7 +394,6 @@ public class Reference
                } else{
                        this.type = type;
                }
-               this.setCacheStrategy(DefaultReferenceCacheStrategy.NewInstance());
        }
 
 // *********************** LISTENER ************************/
@@ -421,16 +417,13 @@ public class Reference
         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
+    // @Transient - must not be transient, since this property needs to be included in all serializations produced by the remote layer
     @Override
     public String getTitleCache(){
         String result = super.getTitleCache();
-        if (isBlank(result)){
+        if (isBlank(result) && !isProtectedTitleCache()){
             this.titleCache = this.getAbbrevTitleCache(true);
         }
         return titleCache;
@@ -494,7 +487,7 @@ public class Reference
 
        @Override
        public void setAbbrevTitle(String abbrevTitle) {
-               this.abbrevTitle = StringUtils.isBlank(abbrevTitle) ? null : abbrevTitle;
+               this.abbrevTitle = isBlank(abbrevTitle) ? null : abbrevTitle;
        }
 
 
@@ -506,7 +499,7 @@ public class Reference
 
        @Override
     public void setEditor(String editor) {
-               this.editor = StringUtils.isBlank(editor)? null : editor;
+               this.editor = isBlank(editor)? null : editor;
        }
 
        @Override
@@ -516,7 +509,7 @@ public class Reference
 
        @Override
     public void setVolume(String volume) {
-               this.volume = StringUtils.isBlank(volume)? null : volume;
+               this.volume = isBlank(volume)? null : volume;
        }
 
        @Override
@@ -526,7 +519,7 @@ public class Reference
 
        @Override
     public void setPages(String pages) {
-               this.pages = StringUtils.isBlank(pages)? null : pages;
+               this.pages = isBlank(pages)? null : pages;
        }
 
        @Override
@@ -536,7 +529,7 @@ public class Reference
 
        @Override
     public void setEdition(String edition) {
-               this.edition = StringUtils.isBlank(edition)? null : edition;
+               this.edition = isBlank(edition)? null : edition;
        }
 
        @Override
@@ -546,7 +539,7 @@ public class Reference
 
        @Override
     public void setIsbn(String isbn) {
-               this.isbn = StringUtils.isBlank(isbn)? null : isbn;
+               this.isbn = isBlank(isbn)? null : isbn;
        }
 
        @Override
@@ -556,7 +549,7 @@ public class Reference
 
        @Override
     public void setIssn(String issn) {
-               this.issn = StringUtils.isBlank(issn)? null : issn;
+               this.issn = isBlank(issn)? null : issn;
        }
 
     @Override
@@ -581,7 +574,7 @@ public class Reference
        }
        @Override
     public void setSeriesPart(String seriesPart) {
-               this.seriesPart = StringUtils.isBlank(seriesPart)? null : seriesPart;
+               this.seriesPart = isBlank(seriesPart)? null : seriesPart;
        }
 
        @Override
@@ -591,40 +584,59 @@ public class Reference
 
        @Override
     public void setOrganization(String organization) {
-               this.organization = StringUtils.isBlank(organization)? null : organization;
+               this.organization = isBlank(organization)? null : organization;
        }
 
        @Override
     public String getPublisher() {
                return publisher;
        }
-
        @Override
     public void setPublisher(String publisher) {
-               this.publisher = StringUtils.isBlank(publisher)? null : publisher;
+               this.publisher = StringUtils.truncate(isBlank(publisher)? null : publisher, 255);
        }
-
-       @Override
+    @Override
     public void setPublisher(String publisher, String placePublished){
-               this.publisher = publisher;
-               this.placePublished = placePublished;
-       }
+        this.publisher = publisher;
+        this.placePublished = placePublished;
+    }
+
+    @Override
+    public String getPublisher2() {
+        return publisher2;
+    }
+    @Override
+    public void setPublisher2(String publisher2) {
+        this.publisher2 = StringUtils.truncate(isBlank(publisher2)? null : publisher2, 255);
+    }
+    @Override
+    public void setPublisher2(String publisher2, String placePublished2){
+        this.publisher2 = publisher2;
+        this.placePublished2 = placePublished2;
+    }
 
        @Override
     public String getPlacePublished() {
                return placePublished;
        }
-
        @Override
     public void setPlacePublished(String placePublished) {
-               this.placePublished = StringUtils.isBlank(placePublished)? null: placePublished;
+               this.placePublished = isBlank(placePublished)? null: placePublished;
        }
 
+    @Override
+    public String getPlacePublished2() {
+        return placePublished2;
+    }
+    @Override
+    public void setPlacePublished2(String placePublished2) {
+        this.placePublished2 = isBlank(placePublished2)? null: placePublished2;
+    }
+
        @Override
     public Institution getInstitution() {
                return institution;
        }
-
        @Override
     public void setInstitution(Institution institution) {
                this.institution = institution;
@@ -634,7 +646,6 @@ public class Reference
     public Institution getSchool() {
                return school;
        }
-
        @Override
     public void setSchool(Institution school) {
                this.school = school;
@@ -644,7 +655,6 @@ public class Reference
     public Reference getInReference() {
                return inReference;
        }
-
        @Override
     public void setInReference(Reference inReference) {
                this.inReference = inReference;
@@ -665,9 +675,6 @@ public class Reference
 
        /**
         * Whether this reference is of the given type
-        *
-        * @param type
-        * @return
         */
        @Override
     public boolean isOfType(ReferenceType type){
@@ -691,7 +698,7 @@ public class Reference
         */
        @Override
     public void setTitle(String title){
-               this.title = StringUtils.isBlank(title)? null : title;
+               this.title = isBlank(title)? null : title;
        }
 
        /**
@@ -719,7 +726,7 @@ public class Reference
     }
 
        public boolean hasDatePublished(){
-               boolean result =  ! ( (this.datePublished == null) || StringUtils.isBlank(datePublished.toString()));
+               boolean result = !((this.datePublished == null) || isBlank(datePublished.toString()));
                return result;
        }
 
@@ -786,7 +793,7 @@ public class Reference
         */
        @Override
     public void setReferenceAbstract(String referenceAbstract) {
-               this.referenceAbstract = StringUtils.isBlank(referenceAbstract)? null : referenceAbstract;
+               this.referenceAbstract = isBlank(referenceAbstract)? null : referenceAbstract;
        }
 
 
@@ -801,14 +808,18 @@ public class Reference
         * 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?
+        * @deprecated currently not supported and not in use, may be removed in future
         */
-       public boolean isNomenclaturallyRelevant(){
+       @Deprecated
+    public boolean isNomenclaturallyRelevant(){
                return this.nomenclaturallyRelevant;
        }
 
        /**
         * @see #isNomenclaturallyRelevant()
+        * @deprecated currently not supported and not in use, may be removed in future
         */
+       @Deprecated
        public void setNomenclaturallyRelevant(boolean nomenclaturallyRelevant){
                this.nomenclaturallyRelevant = nomenclaturallyRelevant;
        }
@@ -833,11 +844,11 @@ public class Reference
        // TODO implement
        @Transient
        public String getCitation(){
-               if (getCacheStrategy() == null){
+               if (cacheStrategy() == null){
                        logger.warn("No CacheStrategy defined for "+ this.getClass() + ": " + this.getUuid());
                        return null;
                }else{
-                       return getCacheStrategy().getTitleCache(this);
+                       return cacheStrategy().getTitleCache(this);
                }
        }
 
@@ -848,15 +859,14 @@ public class Reference
        }
 
     public String generateAbbrevTitle() {
-               return getCacheStrategy().getFullAbbrevTitleString(this);
+               return cacheStrategy().getNomenclaturalTitleCache(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
+        * of this reference contains more date information than (starting) year
         * only the year is returned.
-        * than  attribute.
         */
        @Override
     @Transient
@@ -886,6 +896,31 @@ public class Reference
                }
        }
 
+    /**
+     * Returns a sortable string of the datePublished.start attribute.<BR>
+     * If datePublished is null in-references are called recursively.
+     * Only structured publication data is considered, no freetext or
+     * verbatim date.
+     */
+    @Transient
+    public String getSortableDateString(){
+        VerbatimTimePeriod datePublished = this.getDatePublished();
+        if (datePublished != null ){
+            Partial partial = getDatePublished().getStart();
+            if (partial == null) {
+                partial = getDatePublished().getEnd();
+            }
+            if (partial != null ) {
+                return TimePeriodPartialFormatter.INSTANCE().printSortableDateString(partial);
+            }
+        }
+        if (this.inReference != null){
+            return this.inReference.getSortableDateString();
+        }else {
+            return "zzzz-zz-zz";
+        }
+    }
+
        /**
      * Convenience method that returns a string representation for the publication date / creation
      * of <i>this</i> reference. The string is obtained by
@@ -902,8 +937,6 @@ public class Reference
         }
     }
 
-
-
        @Override
     public int getParsingProblem(){
                return this.parsingProblem;
@@ -964,21 +997,14 @@ public class Reference
        @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;
+               String typeName = this.getType()== null ? "(no type defined)" : this.getType().getLabel();
+               if (cacheStrategy() == null){
+                   throw new IllegalStateException("No CacheStrategy defined for "+ typeName + ": " + this.getUuid());
                }else{
-                   if (getCacheStrategy() instanceof INomenclaturalReferenceCacheStrategy){
-                               return cacheStrategy.getNomenclaturalCitation(this, microReference);
-                       }else {
-                               logger.warn("No INomenclaturalReferenceCacheStrategy defined for "+ typeName + ": " + this.getUuid());
-                               return null;
-                       }
+                   return NomenclaturalSourceFormatter.INSTANCE().format(this, microReference);
                }
        }
 
-
        /**
         * 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>
@@ -1140,19 +1166,123 @@ public class Reference
         setInReference((Reference)proceeding);  //user setter to invoke aspect #1815
        }
 
-//*************************** CACHE STRATEGIES ******************************/
+//**************************** Type *****************************************/
 
-    @Override
-    public INomenclaturalReferenceCacheStrategy getCacheStrategy() {
-       return this.cacheStrategy;
+    public boolean isArticle() {
+        return this.getType().isArticle();
+    }
+    public boolean isBook() {
+        return this.getType().isBook();
+    }
+    public boolean isBookSection() {
+        return this.getType().isBookSection();
+    }
+    public boolean isWebPage() {
+        return this.getType().isWebPage();
+    }
+    public boolean isDatabase() {
+        return this.getType().isDatabase();
+    }
+    public boolean isMap() {
+        return this.getType().isMap();
+    }
+    public boolean isPatent() {
+        return this.getType().isPatent();
+    }
+    public boolean isGeneric() {
+        return this.getType().isGeneric();
+    }
+    public boolean isCdDvd() {
+        return this.getType().isCdDvd();
+    }
+    public boolean isProceedings() {
+        return this.getType().isProceedings();
+    }
+    public boolean isInProceedings() {
+        return this.getType().isInProceedings();
+    }
+    public boolean isJournal() {
+        return this.getType().isJournal();
+    }
+    public boolean isPersonalCommunication() {
+        return this.getType().isPersonalCommunication();
+    }
+    public boolean isThesis() {
+        return this.getType().isThesis();
+    }
+    public boolean isPrintSeries() {
+        return this.getType().isPrintSeries();
+    }
+    /**
+     * @return <code>true</code> if this type is exactly {@link ReferenceType#Section}
+     * @see ReferenceType#isSection()
+     */
+    public boolean isSectionOnly() {
+        return this.getType().isSectionOnly();
+    }
+    /**
+     * Returns <code>true</code> if this reference is part of another reference
+     * (inheriting from {@link ISection}) and therefore may have an in-reference and pages.
+     * @see ReferenceType#isSection()
+     */
+    public boolean isSection() {
+        return this.getType().isSection();
+    }
+    /**
+     * @see ReferenceType#isPrintedUnit()
+     */
+    public boolean isPrintedUnit() {
+        return this.getType().isPrintedUnit();
+    }
+    /**
+     * @return <code>true</code> if the type of this reference
+     *         supports the {@link IDynamicReference} interface. Currently these are
+     *         webpages, databases and maps.
+     */
+    public boolean isDynamic() {
+        return this.getType().isDynamic();
     }
 
-       @Override
-    public void setCacheStrategy(INomenclaturalReferenceCacheStrategy referenceCacheStrategy) {
-               this.cacheStrategy = referenceCacheStrategy;
-       }
+//*************************** CACHE STRATEGIES ******************************/
 
+    @Override
+    protected void initDefaultCacheStrategy() {
+        this.setCacheStrategy(ReferenceDefaultCacheStrategy.NewInstance());
+    }
 
+   @Override
+   public boolean updateCaches(){
+       //TODO shouldn't this be moved to the cache strategy?
+       if (this.equals(this.getInReference())){
+           String message = "-- invalid inreference (self-referencing) --";
+           String oldTitleCache = this.titleCache;
+           this.titleCache = message;
+           return !message.equals(oldTitleCache);
+       }
+       boolean result = super.updateCaches();
+       if (this.protectedAbbrevTitleCache == false){
+           String oldAbbrevTitleCache = this.abbrevTitleCache;
+
+           String newAbbrevTitleCache = getTruncatedCache(cacheStrategy().getNomenclaturalTitleCache(this));
+           if (newAbbrevTitleCache.equals("")){
+               newAbbrevTitleCache = cacheStrategy().getTitleCache(this);
+           }
+
+           if ( oldAbbrevTitleCache == null || ! oldAbbrevTitleCache.equals(newAbbrevTitleCache) ){
+                this.setAbbrevTitleCache(null, false);
+                String newCache = this.getAbbrevTitleCache();
+
+                if (newCache == null){
+                    logger.warn("New abbrevCache should never be null");
+                }
+                if (oldAbbrevTitleCache == null){
+                    logger.info("oldAbbrevTitleCache was illegaly null and has been fixed");
+                }
+                result = true;
+            }
+        }
+        return result;
+    }
 
 //*********************** CLONE ********************************************************/
 
@@ -1165,7 +1295,7 @@ public class Reference
         * @see java.lang.Object#clone()
         */
        @Override
-       public Object clone() {
+       public Reference clone() {
                try {
                        Reference result = (Reference)super.clone();
                        result.setDatePublished(datePublished != null? (VerbatimTimePeriod)datePublished.clone(): null);
@@ -1193,9 +1323,4 @@ public class Reference
                        return super.toString();
                }
        }
-
-
-
-
-}
-
+}
\ No newline at end of file