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;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.FetchType;
+import javax.persistence.ManyToMany;
import javax.persistence.MappedSuperclass;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import org.hibernate.search.annotations.Store;
import org.hibernate.validator.constraints.NotEmpty;
-import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
+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.name.BotanicalName;
-import eu.etaxonomy.cdm.model.name.NonViralName;
-import eu.etaxonomy.cdm.model.name.TaxonNameBase;
+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.taxon.TaxonBase;
+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;
* The originalSource representing that taxon as it was found in IPNI would contain IPNI as the reference, the IPNI id of the taxon and the name of the taxon exactly as it was used in IPNI.
*
* @author m.doering
- * @version 1.0
- * @created 08-Nov-2007 13:06:27
+ * @since 08-Nov-2007 13:06:27
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "IdentifiableEntity", propOrder = {
"credits",
"extensions",
"identifiers",
- "rights",
- "sources"
+ "links",
+ "rights"
})
@Audited
@MappedSuperclass
-public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrategy> extends AnnotatableEntity
+public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrategy>
+ extends SourcedEntityBase<IdentifiableSource>
implements IIdentifiableEntity /*, ISourceable<IdentifiableSource> */ {
- private static final long serialVersionUID = -5610995424730659058L;
+
+ private static final long serialVersionUID = 7912083412108359559L;
private static final Logger logger = Logger.getLogger(IdentifiableEntity.class);
@XmlTransient
@XmlElement(name = "TitleCache", required = true)
@XmlJavaTypeAdapter(FormattedTextAdapter.class)
- @Column(name="titleCache")
+ @Column(name="titleCache", length=800) //see #1592
@Match(value=MatchMode.CACHE, cacheReplaceMode=ReplaceMode.ALL)
- @NotEmpty(groups = Level2.class) // implictly NotNull
- @Size(max = 800) //see #1592
+ @NotEmpty(groups = Level2.class) // implicitly NotNull
@Fields({
@Field(store=Store.YES),
// If the field is only needed for sorting and nothing else, you may configure it as
@XmlElementWrapper(name = "Rights", nillable = true)
@XmlElement(name = "Rights")
- @OneToMany(fetch = FetchType.LAZY, orphanRemoval=true)
- @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
+ @ManyToMany(fetch = FetchType.LAZY /*, orphanRemoval=false*/) //#5762 M:N now
+ @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
//TODO
@Merge(MergeMode.ADD_CLONE)
@NotNull
- private Set<Rights> rights = new HashSet<Rights>();
+ private Set<Rights> rights = new HashSet<>();
@XmlElementWrapper(name = "Credits", nillable = true)
@XmlElement(name = "Credit")
//TODO
@Merge(MergeMode.ADD_CLONE)
@NotNull
- private List<Credit> credits = new ArrayList<Credit>();
+ private List<Credit> credits = new ArrayList<>();
@XmlElementWrapper(name = "Extensions", nillable = true)
@XmlElement(name = "Extension")
@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
@Merge(MergeMode.ADD_CLONE)
@NotNull
- private Set<Extension> extensions = new HashSet<Extension>();
+ private Set<Extension> extensions = new HashSet<>();
@XmlElementWrapper(name = "Identifiers", nillable = true)
@XmlElement(name = "Identifier")
@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
@Merge(MergeMode.ADD_CLONE)
@NotNull
- private List<Identifier> identifiers = new ArrayList<Identifier>();
+ private List<Identifier> identifiers = new ArrayList<>();
- @XmlElementWrapper(name = "Sources", nillable = true)
- @XmlElement(name = "IdentifiableSource")
- @OneToMany(fetch = FetchType.LAZY, orphanRemoval=true)
+ @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)
- @NotNull
- private Set<IdentifiableSource> sources = new HashSet<IdentifiableSource>();
+ private Set<ExternalLink> links = new HashSet<>();
@XmlTransient
@Transient
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;
}
}
this.titleCache = generateTitle();
this.titleCache = getTruncatedCache(this.titleCache) ;
}
+ //removed due to #5849
+// if(StringUtils.isBlank(titleCache)){
+// titleCache = this.toString();
+// }
return titleCache;
}
this.protectedTitleCache = protectCache;
}
+ @Override
+ public String resetTitleCache() {
+ if(!protectedTitleCache){
+ titleCache = null;
+ }
+ return getTitleCache();
+ }
+
/**
* @param cache
* @return
return cache;
}
+
+ @Override
+ public boolean isProtectedTitleCache() {
+ return protectedTitleCache;
+ }
+
+ @Override
+ public void setProtectedTitleCache(boolean protectedTitleCache) {
+ this.protectedTitleCache = protectedTitleCache;
+ }
+
+ /**
+ *
+ * @return true, if the current state of the titleCache (without generating it new)
+ * is <code>null</code> or the empty string. This is primarily meant for internal use.
+ */
+ public boolean hasEmptyTitleCache(){
+ return this.titleCache == null || "".equals(this.titleCache);
+ }
+
+ public boolean updateCaches(){
+ if (this.protectedTitleCache == false){
+ String oldTitleCache = this.titleCache;
+
+ @SuppressWarnings("unchecked")
+ String newTitleCache = getCacheStrategy().getTitleCache(this);
+
+ if ( oldTitleCache == null || ! oldTitleCache.equals(newTitleCache) ){
+ this.setTitleCache(null, false);
+ String newCache = this.getTitleCache();
+
+ if (newCache == null){
+ logger.warn("newCache should never be null");
+ }
+ if (oldTitleCache == null){
+ logger.info("oldTitleCache was illegaly null and has been fixed");
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Updates the caches with the given cache strategy
+ * @param entityCacheStrategy
+ * @return <code>true</code> if some cache was updated, <code>false</code> otherwise
+ */
+ public boolean updateCaches(S entityCacheStrategy){
+ S oldCacheStrategy = this.getCacheStrategy();
+ this.cacheStrategy = entityCacheStrategy != null? entityCacheStrategy : this.getCacheStrategy();
+ boolean result = this.updateCaches();
+ this.cacheStrategy = oldCacheStrategy;
+ return result;
+ }
+
//**************************************************************************************
@Override
@Override
public Set<Rights> getRights() {
if(rights == null) {
- this.rights = new HashSet<Rights>();
+ this.rights = new HashSet<>();
}
return this.rights;
}
}
+//********************** 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) {
- this.credits = new ArrayList<Credit>();
+ this.credits = new ArrayList<>();
}
return this.credits;
}
getCredits().remove(index);
}
- /* (non-Javadoc)
- * @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#getIdentifiers()
- */
+ @Override
+ public boolean replaceCredit(Credit newObject, Credit oldObject){
+ return replaceInList(this.credits, newObject, oldObject);
+ }
+
+
@Override
public List<Identifier> getIdentifiers(){
if(this.identifiers == null) {
- this.identifiers = new ArrayList<Identifier>();
+ this.identifiers = new ArrayList<>();
}
return this.identifiers;
}
* @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
* @return a set of identifier value strings
*/
public Set<String> getIdentifiers(UUID identifierTypeUuid){
- Set<String> result = new HashSet<String>();
+ Set<String> result = new HashSet<>();
for (Identifier identifier : getIdentifiers()){
- if (identifier.getType().getUuid().equals(identifierTypeUuid)){
+ 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(this, identifier, identifierType);
+ Identifier result = Identifier.NewInstance(identifier, identifierType);
+ addIdentifier(result);
return result;
}
- @Override
- public void addIdentifier(int index, Identifier identifier){
+ @Override
+ public void addIdentifier(Integer index, Identifier identifier){
if (identifier != null){
- if (identifier.getIdentifiedObj() != null && ! identifier.getIdentifiedObj().equals(this)){
- identifier.getIdentifiedObj().removeIdentifier(identifier);
- }
- identifier.setIdentifiedObj(this);
//deduplication
int oldIndex = getIdentifiers().indexOf(identifier);
if(oldIndex > -1){
getIdentifiers().remove(identifier);
- if (oldIndex < index){
+ if (index != null && oldIndex < index){
index--;
}
}
- getIdentifiers().add(index, identifier);
+
+ if (index != null){
+ getIdentifiers().add(index, identifier);
+ }else{
+ getIdentifiers().add(identifier);
+ }
}
}
@Override
public void addIdentifier(Identifier identifier){
- addIdentifier(getIdentifiers().size(), identifier);
+ addIdentifier(null, identifier);
}
@Override
public void removeIdentifier(Identifier identifier){
if (identifier != null){
- identifier.setIdentifiedObj(null);
getIdentifiers().remove(identifier);
}
}
getIdentifiers().remove(index);
}
+ @Override
+ public boolean replaceIdentifier(Identifier newObject, Identifier oldObject){
+ return replaceInList(this.identifiers, newObject, oldObject);
+ }
+
+
@Override
public Set<Extension> getExtensions(){
if(extensions == null) {
- this.extensions = new HashSet<Extension>();
+ this.extensions = new HashSet<>();
}
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
/**
* @param extensionTypeUuid
* @return a Set of extension value strings
+ * @see #hasExtension(UUID, String)
*/
public Set<String> getExtensions(UUID extensionTypeUuid){
- Set<String> result = new HashSet<String>();
+ Set<String> result = new HashSet<>();
for (Extension extension : getExtensions()){
- if (extension.getType().getUuid().equals(extensionTypeUuid)){
+ if (extension.getType() != null && extension.getType().getUuid().equals(extensionTypeUuid)){
result.add(extension.getValue());
}
}
return result;
}
+ /**
+ * @see #getExtensionsConcat(Collection, String)
+ */
+ public String getExtensionsConcat(UUID extensionTypeUuid, String separator){
+ String result = null;
+ for (Extension extension : getExtensions()){
+ 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
+ * an Extension exists with given type and 'value' is <code>null</code>.
+ * @param extensionTypeUuid
+ * @param value
+ * @see #hasExtension(ExtensionType, String)
+ * @see #getExtensions(UUID)
+ */
+ public boolean hasExtension(UUID extensionTypeUuid, String value) {
+ for (String ext : this.getExtensions(extensionTypeUuid)){
+ if (CdmUtils.nullSafeEqual(ext, value)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @see #hasExtension(UUID, String)
+ */
+ public boolean hasExtension(ExtensionType extensionType, String value) {
+ return hasExtension(extensionType.getUuid(), value);
+ }
+
+ @Override
public void addExtension(String value, ExtensionType extensionType){
Extension.NewInstance(this, value, extensionType);
}
@Override
public void addExtension(Extension extension){
if (extension != null){
- extension.setExtendedObj(this);
getExtensions().add(extension);
}
}
@Override
public void removeExtension(Extension extension){
if (extension != null){
- extension.setExtendedObj(null);
getExtensions().remove(extension);
}
}
- @Override
- public boolean isProtectedTitleCache() {
- return protectedTitleCache;
- }
-
- @Override
- public void setProtectedTitleCache(boolean protectedTitleCache) {
- this.protectedTitleCache = protectedTitleCache;
- }
-
- @Override
- public Set<IdentifiableSource> getSources() {
- if(sources == null) {
- this.sources = new HashSet<IdentifiableSource>();
- }
- return this.sources;
- }
-
@Override
public void addSource(IdentifiableSource source) {
if (source != null){
- IdentifiableEntity<?> oldSourcedObj = source.getSourcedObj();
- if (oldSourcedObj != null && oldSourcedObj != this){
- oldSourcedObj.getSources().remove(source);
- }
getSources().add(source);
- source.setSourcedObj(this);
}
}
public void addSources(Set<IdentifiableSource> sources) {
if (sources != null){
for (IdentifiableSource source: sources){
- IdentifiableEntity<?> oldSourcedObj = source.getSourcedObj();
- if (oldSourcedObj != null && oldSourcedObj != this){
- oldSourcedObj.getSources().remove(source);
- }
getSources().add(source);
- source.setSourcedObj(this);
}
}
}
@Override
- public void removeSources() {
- this.sources.clear();
- }
-
- @Override
- public IdentifiableSource addSource(OriginalSourceType type, String id, String idNamespace, Reference citation, String microCitation) {
- if (id == null && idNamespace == null && citation == null && microCitation == null){
- return null;
- }
- IdentifiableSource source = IdentifiableSource.NewInstance(type, id, idNamespace, citation, microCitation);
- addSource(source);
- return source;
- }
-
-
- @Override
- public IdentifiableSource addImportSource(String id, String idNamespace, Reference<?> citation, String microCitation) {
- if (id == null && idNamespace == null && citation == null && microCitation == null){
- return null;
- }
- IdentifiableSource source = IdentifiableSource.NewInstance(OriginalSourceType.Import, id, idNamespace, citation, microCitation);
- addSource(source);
- return source;
- }
-
-
- @Override
- public void removeSource(IdentifiableSource source) {
- getSources().remove(source);
+ protected IdentifiableSource createNewSource(OriginalSourceType type, String idInSource, String idNamespace,
+ Reference reference, String microReference, String originalInfo, ICdmTarget target) {
+ return IdentifiableSource.NewInstance(type, idInSource, idNamespace, reference, microReference, originalInfo, target);
}
//******************************** TO STRING *****************************************************/
- /* (non-Javadoc)
- * @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#toString()
- */
- @Override
+ @Override
public String toString() {
String result;
- if (titleCache == null){
+ if (isBlank(titleCache)){
result = super.toString();
}else{
result = this.titleCache;
}
- public int compareTo(IdentifiableEntity identifiableEntity) {
-
- int result = 0;
-
- if (identifiableEntity == null) {
- throw new NullPointerException("Cannot compare to null.");
- }
-
- // First, compare the name cache.
- // TODO: Avoid using instanceof operator
- // Use Class.getDeclaredMethod() instead to find out whether class has getNameCache() method?
-
- String specifiedNameCache = "";
- String thisNameCache = "";
- String specifiedTitleCache = "";
- String thisTitleCache = "";
- String specifiedReferenceTitleCache = "";
- String thisReferenceTitleCache = "";
- String thisGenusString = "";
- String specifiedGenusString = "";
- int thisrank_order = 0;
- final String HYBRID_SIGN = "\u00D7";
- final String QUOT_SIGN = "[\\u02BA\\u0022\\u0022]";
- //TODO we can remove all the deproxies here except for the first one
- identifiableEntity = HibernateProxyHelper.deproxy(identifiableEntity, IdentifiableEntity.class);
- if(identifiableEntity instanceof NonViralName) {
- specifiedNameCache = HibernateProxyHelper.deproxy(identifiableEntity, NonViralName.class).getNameCache();
- specifiedTitleCache = identifiableEntity.getTitleCache();
- if (identifiableEntity instanceof BotanicalName){
- if (((BotanicalName)identifiableEntity).isAutonym()){
- boolean isProtected = false;
- String oldNameCache = ((BotanicalName) identifiableEntity).getNameCache();
- if ( ((BotanicalName)identifiableEntity).isProtectedNameCache()){
- isProtected = true;
- }
- ((BotanicalName)identifiableEntity).setProtectedNameCache(false);
- ((BotanicalName)identifiableEntity).setNameCache(null, false);
- specifiedNameCache = ((BotanicalName) identifiableEntity).getNameCache();
- ((BotanicalName)identifiableEntity).setNameCache(oldNameCache, isProtected);
-
- }
- }
-
- } else if(identifiableEntity instanceof TaxonBase) {
- TaxonBase taxonBase = HibernateProxyHelper.deproxy(identifiableEntity, TaxonBase.class);
-
- TaxonNameBase<?,?> taxonNameBase = taxonBase.getName();
-
-
- NonViralName nonViralName = HibernateProxyHelper.deproxy(taxonNameBase, NonViralName.class);
- specifiedNameCache = nonViralName.getNameCache();
- specifiedTitleCache = taxonNameBase.getTitleCache();
-
- specifiedReferenceTitleCache = ((TaxonBase)identifiableEntity).getSec().getTitleCache();
- Reference reference = taxonBase.getSec();
- if (reference != null) {
- reference = HibernateProxyHelper.deproxy(reference, Reference.class);
- specifiedReferenceTitleCache = reference.getTitleCache();
- }
- }
-
- if(this.isInstanceOf(NonViralName.class)) {
- thisNameCache = HibernateProxyHelper.deproxy(this, NonViralName.class).getNameCache();
- thisTitleCache = getTitleCache();
-
- if (this instanceof BotanicalName){
- if (((BotanicalName)this).isAutonym()){
- boolean isProtected = false;
- String oldNameCache = ((BotanicalName) this).getNameCache();
- if ( ((BotanicalName)this).isProtectedNameCache()){
- isProtected = true;
- }
- ((BotanicalName)this).setProtectedNameCache(false);
- ((BotanicalName)this).setNameCache(null, false);
- thisNameCache = ((BotanicalName) this).getNameCache();
- ((BotanicalName)this).setNameCache(oldNameCache, isProtected);
- }
- }
- } else if(this.isInstanceOf(TaxonBase.class)) {
- TaxonNameBase<?,?> taxonNameBase= HibernateProxyHelper.deproxy(this, TaxonBase.class).getName();
- NonViralName nonViralName = HibernateProxyHelper.deproxy(taxonNameBase, NonViralName.class);
- thisNameCache = nonViralName.getNameCache();
- thisTitleCache = taxonNameBase.getTitleCache();
- thisReferenceTitleCache = ((TaxonBase)this).getSec().getTitleCache();
- thisGenusString = nonViralName.getGenusOrUninomial();
- }
-
- // Compare name cache of taxon names
-
-
-
- if (!specifiedNameCache.equals("") && !thisNameCache.equals("")) {
-
- thisNameCache = thisNameCache.replaceAll(HYBRID_SIGN, "");
- thisNameCache = thisNameCache.replaceAll(QUOT_SIGN, "");
-
-
- specifiedNameCache = specifiedNameCache.replaceAll(HYBRID_SIGN, "");
- specifiedNameCache = specifiedNameCache.replaceAll(QUOT_SIGN, "");
-
-
- result = thisNameCache.compareTo(specifiedNameCache);
- }
-
- // Compare title cache of taxon names
-
- if ((result == 0) && (!specifiedTitleCache.equals("") || !thisTitleCache.equals(""))) {
- thisTitleCache = thisTitleCache.replaceAll(HYBRID_SIGN, "");
- thisTitleCache = thisTitleCache.replaceAll(QUOT_SIGN, "");
-
- specifiedTitleCache = specifiedTitleCache.replaceAll(HYBRID_SIGN, "");
- specifiedTitleCache = specifiedTitleCache.replaceAll(QUOT_SIGN, "");
- result = thisTitleCache.compareTo(specifiedTitleCache);
- }
-
- // Compare title cache of taxon references
-
- if ((result == 0) && (!specifiedReferenceTitleCache.equals("") || !thisReferenceTitleCache.equals(""))) {
- result = thisReferenceTitleCache.compareTo(specifiedReferenceTitleCache);
- }
-
- return result;
- }
-
/**
* Returns the {@link eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy cache strategy} used to generate
* several strings corresponding to <i>this</i> identifiable entity
* @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;
}
}
}
+ /**
+ * 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<Extension>();
+ 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<Identifier>();
- for (Identifier<?> identifier : getIdentifiers() ){
- Identifier<?> newIdentifier = (Identifier<?>)identifier.clone();
+ result.identifiers = new ArrayList<>();
+ for (Identifier identifier : getIdentifiers() ){
+ Identifier newIdentifier = identifier.clone();
result.addIdentifier(newIdentifier);
}
- //OriginalSources
- result.sources = new HashSet<IdentifiableSource>();
- for (IdentifiableSource source : getSources()){
- IdentifiableSource newSource = (IdentifiableSource)source.clone();
- result.addSource(newSource);
+ //Rights - reusable since #5762
+ result.rights = new HashSet<>();
+ for(Rights right : getRights()) {
+ result.addRights(right);
}
- //Rights
- result.rights = new HashSet<Rights>();
- for(Rights rights : getRights()) {
- result.addRights(rights);
- }
-
-
//Credits
- result.credits = new ArrayList<Credit>();
+ result.credits = new ArrayList<>();
for(Credit credit : getCredits()) {
- result.addCredit(credit);
+ 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
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