remove generics from Identifier class
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / common / IdentifiableEntity.java
index 03ca7758347ebce0d16d9e95f7ff17d9ebe61dcb..05a247e7641735b8e818fcf0f84ab37af926e249 100644 (file)
@@ -13,6 +13,7 @@ package eu.etaxonomy.cdm.model.common;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -35,7 +36,6 @@ 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.hibernate.annotations.Cascade;
 import org.hibernate.annotations.CascadeType;
@@ -50,11 +50,17 @@ import org.hibernate.search.annotations.Store;
 import org.hibernate.validator.constraints.NotEmpty;
 
 import eu.etaxonomy.cdm.common.CdmUtils;
+import eu.etaxonomy.cdm.common.URI;
 import eu.etaxonomy.cdm.hibernate.search.StripHtmlBridge;
 import eu.etaxonomy.cdm.jaxb.FormattedTextAdapter;
 import eu.etaxonomy.cdm.jaxb.LSIDAdapter;
+import eu.etaxonomy.cdm.model.media.ExternalLink;
 import eu.etaxonomy.cdm.model.media.Rights;
+import eu.etaxonomy.cdm.model.reference.ICdmTarget;
+import eu.etaxonomy.cdm.model.reference.OriginalSourceBase;
+import eu.etaxonomy.cdm.model.reference.OriginalSourceType;
 import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.cdm.model.term.DefinedTerm;
 import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
 import eu.etaxonomy.cdm.strategy.match.Match;
 import eu.etaxonomy.cdm.strategy.match.Match.ReplaceMode;
@@ -82,6 +88,7 @@ import eu.etaxonomy.cdm.validation.Level2;
     "credits",
     "extensions",
     "identifiers",
+    "links",
     "rights"
 })
 @Audited
@@ -143,7 +150,7 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
 
     @XmlElementWrapper(name = "Extensions", nillable = true)
     @XmlElement(name = "Extension")
-    @OneToMany(fetch = FetchType.LAZY)
+    @OneToMany(fetch = FetchType.LAZY, orphanRemoval=true)
     @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
     @Merge(MergeMode.ADD_CLONE)
     @NotNull
@@ -158,6 +165,13 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
     @NotNull
     private List<Identifier> identifiers = new ArrayList<>();
 
+    @XmlElementWrapper(name = "Links", nillable = true)
+    @XmlElement(name = "Link")
+    @OneToMany(fetch=FetchType.LAZY, orphanRemoval=true)
+    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
+    @Merge(MergeMode.ADD_CLONE)
+    private Set<ExternalLink> links = new HashSet<>();
+
     @XmlTransient
     @Transient
     protected S cacheStrategy;
@@ -171,7 +185,9 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
         PropertyChangeListener listener = new PropertyChangeListener() {
             @Override
             public void propertyChange(PropertyChangeEvent ev) {
-                if (! "titleCache".equals(ev.getPropertyName()) && !"cacheStrategy".equals(ev.getPropertyName()) && ! isProtectedTitleCache()){
+                if (! "titleCache".equals(ev.getPropertyName())
+                        && !"cacheStrategy".equals(ev.getPropertyName())
+                        && ! isProtectedTitleCache()){
                     titleCache = null;
                 }
             }
@@ -224,6 +240,14 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
         this.protectedTitleCache = protectCache;
     }
 
+    @Override
+    public String resetTitleCache() {
+        if(!protectedTitleCache){
+            titleCache = null;
+        }
+        return getTitleCache();
+    }
+
     /**
      * @param cache
      * @return
@@ -262,7 +286,8 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
         if (this.protectedTitleCache == false){
             String oldTitleCache = this.titleCache;
 
-            String newTitleCache = cacheStrategy.getTitleCache(this);
+            @SuppressWarnings("unchecked")
+            String newTitleCache = getCacheStrategy().getTitleCache(this);
 
             if ( oldTitleCache == null   || ! oldTitleCache.equals(newTitleCache) ){
                 this.setTitleCache(null, false);
@@ -321,6 +346,36 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
     }
 
 
+//********************** External Links **********************************************
+
+
+    public Set<ExternalLink> getLinks(){
+        return this.links;
+    }
+    public void setLinks(Set<ExternalLink> links){
+        this.links = links;
+    }
+    public void addLink(ExternalLink link){
+        if (link != null){
+            links.add(link);
+        }
+    }
+    public ExternalLink addLinkWebsite(URI uri, String description, Language descriptionLanguage){
+        ExternalLink link = null;
+        if (uri != null || description != null || descriptionLanguage != null){
+            link = ExternalLink.NewWebSiteInstance(uri, description, descriptionLanguage);
+            links.add(link);
+        }
+        return link;
+    }
+    public void removeLink(ExternalLink link){
+        if(links.contains(link)) {
+            links.remove(link);
+        }
+    }
+
+//********************** CREDITS **********************************************
+
     @Override
     public List<Credit> getCredits() {
         if(credits == null) {
@@ -373,7 +428,7 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
      * @return a set of identifier value strings
      */
     public Set<String> getIdentifiers(DefinedTerm type){
-       return getIdentifiers(type.getUuid());
+       return getIdentifiers(type == null? null :type.getUuid());
     }
     /**
      * @param identifierTypeUuid
@@ -381,17 +436,29 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
      */
     public Set<String> getIdentifiers(UUID identifierTypeUuid){
         Set<String> result = new HashSet<>();
-        for (Identifier<?> identifier : getIdentifiers()){
-            if (identifier.getType().getUuid().equals(identifierTypeUuid)){
+        for (Identifier identifier : getIdentifiers()){
+            if ( (identifier.getType()== null && identifierTypeUuid == null)
+                || (identifier.getType().getUuid().equals(identifierTypeUuid))){
                 result.add(identifier.getIdentifier());
             }
         }
         return result;
     }
 
+    public Set<Identifier> getIdentifiers_(UUID identifierTypeUuid){
+        Set<Identifier> result = new HashSet<>();
+        for (Identifier identifier : getIdentifiers()){
+            if ( (identifier.getType()== null && identifierTypeUuid == null)
+                || (identifier.getType().getUuid().equals(identifierTypeUuid))){
+                result.add(identifier);
+            }
+        }
+        return result;
+    }
+
     @Override
     public Identifier addIdentifier(String identifier, DefinedTerm identifierType){
-       Identifier<?> result = Identifier.NewInstance(identifier, identifierType);
+       Identifier result = Identifier.NewInstance(identifier, identifierType);
        addIdentifier(result);
        return result;
     }
@@ -445,6 +512,15 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
         }
         return this.extensions;
     }
+    public Set<Extension> getFilteredExtensions(UUID extensionTypeUuid){
+        Set<Extension> result = new HashSet<>();
+        for (Extension extension : getExtensions()){
+            if (extension.getType() != null && extension.getType().getUuid().equals(extensionTypeUuid)){
+                result.add(extension);
+            }
+        }
+        return result;
+     }
     /**
      * @param type
      * @return a Set of extension value strings
@@ -467,16 +543,37 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
         return result;
     }
 
+    /**
+     * @see #getExtensionsConcat(Collection, String)
+     */
     public String getExtensionsConcat(UUID extensionTypeUuid, String separator){
         String result = null;
         for (Extension extension : getExtensions()){
-            if (extension.getType().getUuid().equals(extensionTypeUuid)){
+            if (extension.getType() != null && extension.getType().getUuid().equals(extensionTypeUuid)){
                 result = CdmUtils.concat(separator, result, extension.getValue());
             }
         }
         return result;
     }
 
+    /**
+     * Return all extensions matching the given extension type as
+     * concatenated string. If extensionTypeUuids is a sorted collection
+     * it is given in the correct order.
+     * @param extensionTypeUuids collection of the extension types to be considered
+     * @param separator the separator for concatenation
+     * @return the concatenated extension string
+     * @see #getExtensionsConcat(Collection, String)
+     */
+    public String getExtensionsConcat(Collection<UUID> extensionTypeUuids, String separator){
+        String result = null;
+        for (UUID uuid : extensionTypeUuids){
+            String extension = getExtensionsConcat(uuid, separator);
+            result = CdmUtils.concat(separator, result, extension);
+        }
+        return result;
+    }
+
     /**
      * Has this entity an extension of given type with value 'value'.
      * If value is <code>null</code> <code>true</code> is returned if
@@ -536,14 +633,10 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
         }
     }
 
-
-    /**
-     * {@inheritDoc}
-     */
     @Override
     protected IdentifiableSource createNewSource(OriginalSourceType type, String idInSource, String idNamespace,
-            Reference reference, String microReference, String originalInfo) {
-        return IdentifiableSource.NewInstance(type, idInSource, idNamespace, reference, microReference, originalInfo);
+            Reference reference, String microReference, String originalInfo, ICdmTarget target) {
+        return IdentifiableSource.NewInstance(type, idInSource, idNamespace, reference, microReference, originalInfo, target);
     }
 
 //******************************** TO STRING *****************************************************/
@@ -551,7 +644,7 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
     @Override
     public String toString() {
         String result;
-        if (StringUtils.isBlank(titleCache)){
+        if (isBlank(titleCache)){
             result = super.toString();
         }else{
             result = this.titleCache;
@@ -569,12 +662,11 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
      * @see     eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy
      */
     public S getCacheStrategy() {
+        if (this.cacheStrategy == null){
+            initDefaultCacheStrategy();
+        }
         return this.cacheStrategy;
     }
-    /**
-     * @see    #getCacheStrategy()
-     */
-
     public void setCacheStrategy(S cacheStrategy) {
         this.cacheStrategy = cacheStrategy;
     }
@@ -589,23 +681,30 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
         }
     }
 
+    /**
+     * Subclasses should implement setting the default cache strategy
+     */
+    protected abstract void initDefaultCacheStrategy();
+
 //****************** CLONE ************************************************/
 
     @Override
-    public Object clone() throws CloneNotSupportedException{
-        IdentifiableEntity<?> result = (IdentifiableEntity<?>)super.clone();
+    public IdentifiableEntity<S> clone() throws CloneNotSupportedException{
+
+        @SuppressWarnings("unchecked")
+        IdentifiableEntity<S> result = (IdentifiableEntity<S>)super.clone();
 
         //Extensions
         result.extensions = new HashSet<>();
         for (Extension extension : getExtensions() ){
-            Extension newExtension = (Extension)extension.clone();
+            Extension newExtension = extension.clone();
             result.addExtension(newExtension);
         }
 
         //Identifier
         result.identifiers = new ArrayList<>();
-        for (Identifier<?> identifier : getIdentifiers() ){
-               Identifier<?> newIdentifier = (Identifier<?>)identifier.clone();
+        for (Identifier identifier : getIdentifiers() ){
+               Identifier newIdentifier = identifier.clone();
             result.addIdentifier(newIdentifier);
         }
 
@@ -618,10 +717,17 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
         //Credits
         result.credits = new ArrayList<>();
         for(Credit credit : getCredits()) {
-            Credit newCredit = (Credit)credit.clone();
+            Credit newCredit = credit.clone();
             result.addCredit(newCredit);
         }
 
+        //Links
+        result.links = new HashSet<>();
+        for(ExternalLink link : getLinks()) {
+            ExternalLink newLink = link.clone();
+            result.addLink(newLink);
+        }
+
         //no changes to: lsid, titleCache, protectedTitleCache
 
         //empty titleCache
@@ -629,9 +735,7 @@ public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrat
             result.titleCache = null;
         }
 
-        result.initListener();
+        result.initListener();  //TODO why do we need this, isnt't the listener in constructor enough?
         return result;
     }
-
-
-}
+}
\ No newline at end of file