1 |
9479da48
|
Andreas Müller
|
/**
|
2 |
|
|
* Copyright (C) 2007 EDIT
|
3 |
22a09e94
|
Andreas Kohlbecker
|
* European Distributed Institute of Taxonomy
|
4 |
9479da48
|
Andreas Müller
|
* http://www.e-taxonomy.eu
|
5 |
22a09e94
|
Andreas Kohlbecker
|
*
|
6 |
9479da48
|
Andreas Müller
|
* The contents of this file are subject to the Mozilla Public License Version 1.1
|
7 |
|
|
* See LICENSE.TXT at the top of this package for the full license terms.
|
8 |
|
|
*/
|
9 |
|
|
|
10 |
|
|
package eu.etaxonomy.cdm.model.common;
|
11 |
|
|
|
12 |
|
|
|
13 |
5ea47892
|
Andreas Müller
|
import java.beans.PropertyChangeEvent;
|
14 |
|
|
import java.beans.PropertyChangeListener;
|
15 |
db45aff9
|
Andreas Müller
|
import java.util.ArrayList;
|
16 |
0ec8aee7
|
Andreas Müller
|
import java.util.HashSet;
|
17 |
db45aff9
|
Andreas Müller
|
import java.util.List;
|
18 |
0ec8aee7
|
Andreas Müller
|
import java.util.Set;
|
19 |
43b314ef
|
Andreas Müller
|
import java.util.UUID;
|
20 |
9479da48
|
Andreas Müller
|
|
21 |
0ec8aee7
|
Andreas Müller
|
import javax.persistence.Column;
|
22 |
ee91bcd9
|
ben.clark
|
import javax.persistence.Embedded;
|
23 |
f6765014
|
ben.clark
|
import javax.persistence.FetchType;
|
24 |
0ec8aee7
|
Andreas Müller
|
import javax.persistence.MappedSuperclass;
|
25 |
|
|
import javax.persistence.OneToMany;
|
26 |
4208745a
|
ben.clark
|
import javax.persistence.Transient;
|
27 |
a641fad9
|
ben.clark
|
import javax.validation.constraints.NotNull;
|
28 |
|
|
import javax.validation.constraints.Size;
|
29 |
70440a7d
|
a.babadshanjan
|
import javax.xml.bind.annotation.XmlAccessType;
|
30 |
|
|
import javax.xml.bind.annotation.XmlAccessorType;
|
31 |
|
|
import javax.xml.bind.annotation.XmlElement;
|
32 |
|
|
import javax.xml.bind.annotation.XmlElementWrapper;
|
33 |
|
|
import javax.xml.bind.annotation.XmlTransient;
|
34 |
|
|
import javax.xml.bind.annotation.XmlType;
|
35 |
ee91bcd9
|
ben.clark
|
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
36 |
9479da48
|
Andreas Müller
|
|
37 |
0ec8aee7
|
Andreas Müller
|
import org.apache.log4j.Logger;
|
38 |
|
|
import org.hibernate.annotations.Cascade;
|
39 |
|
|
import org.hibernate.annotations.CascadeType;
|
40 |
db45aff9
|
Andreas Müller
|
import org.hibernate.annotations.IndexColumn;
|
41 |
a13c5f66
|
Andreas Müller
|
import org.hibernate.envers.Audited;
|
42 |
|
|
import org.hibernate.search.annotations.Analyze;
|
43 |
22a09e94
|
Andreas Kohlbecker
|
import org.hibernate.search.annotations.Field;
|
44 |
f6765014
|
ben.clark
|
import org.hibernate.search.annotations.FieldBridge;
|
45 |
ac1a821b
|
Andreas Kohlbecker
|
import org.hibernate.search.annotations.Fields;
|
46 |
0930d1c2
|
Andreas Kohlbecker
|
import org.hibernate.search.annotations.Store;
|
47 |
a641fad9
|
ben.clark
|
import org.hibernate.validator.constraints.NotEmpty;
|
48 |
9479da48
|
Andreas Müller
|
|
49 |
8b827269
|
Andreas Müller
|
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
|
50 |
0930d1c2
|
Andreas Kohlbecker
|
import eu.etaxonomy.cdm.hibernate.search.StripHtmlBridge;
|
51 |
ee91bcd9
|
ben.clark
|
import eu.etaxonomy.cdm.jaxb.FormattedTextAdapter;
|
52 |
|
|
import eu.etaxonomy.cdm.jaxb.LSIDAdapter;
|
53 |
0ec8aee7
|
Andreas Müller
|
import eu.etaxonomy.cdm.model.media.Rights;
|
54 |
3b98b0db
|
Katja Luther
|
import eu.etaxonomy.cdm.model.name.BotanicalName;
|
55 |
bb430412
|
a.babadshanjan
|
import eu.etaxonomy.cdm.model.name.NonViralName;
|
56 |
168723a2
|
a.babadshanjan
|
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
|
57 |
1d36aa54
|
Andreas Müller
|
import eu.etaxonomy.cdm.model.reference.Reference;
|
58 |
168723a2
|
a.babadshanjan
|
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
|
59 |
4208745a
|
ben.clark
|
import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
|
60 |
57ea5ac1
|
Andreas Müller
|
import eu.etaxonomy.cdm.strategy.match.Match;
|
61 |
dcf662bb
|
Andreas Müller
|
import eu.etaxonomy.cdm.strategy.match.Match.ReplaceMode;
|
62 |
377f17a0
|
n.hoffmann
|
import eu.etaxonomy.cdm.strategy.match.MatchMode;
|
63 |
53befb32
|
Andreas Müller
|
import eu.etaxonomy.cdm.strategy.merge.Merge;
|
64 |
|
|
import eu.etaxonomy.cdm.strategy.merge.MergeMode;
|
65 |
a641fad9
|
ben.clark
|
import eu.etaxonomy.cdm.validation.Level2;
|
66 |
9479da48
|
Andreas Müller
|
|
67 |
|
|
/**
|
68 |
33f9b501
|
m.doering
|
* Superclass for the primary CDM classes that can be referenced from outside via LSIDs and contain a simple generated title string as a label for human reading.
|
69 |
|
|
* All subclasses inherit the ability to store additional properties that are stored as {@link Extension Extensions}, basically a string value with a type term.
|
70 |
22a09e94
|
Andreas Kohlbecker
|
* Any number of right statements can be attached as well as multiple {@link OriginalSourceBase} objects.
|
71 |
33f9b501
|
m.doering
|
* Original sources carry a reference to the source, an ID within that source and the original title/label of this object as it was used in that source (originalNameString).
|
72 |
|
|
* A Taxon for example that was taken from 2 sources like FaunaEuropaea and IPNI would have two originalSource objects.
|
73 |
|
|
* 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.
|
74 |
22a09e94
|
Andreas Kohlbecker
|
*
|
75 |
9479da48
|
Andreas Müller
|
* @author m.doering
|
76 |
|
|
* @version 1.0
|
77 |
|
|
* @created 08-Nov-2007 13:06:27
|
78 |
|
|
*/
|
79 |
70440a7d
|
a.babadshanjan
|
@XmlAccessorType(XmlAccessType.FIELD)
|
80 |
|
|
@XmlType(name = "IdentifiableEntity", propOrder = {
|
81 |
|
|
"lsid",
|
82 |
|
|
"titleCache",
|
83 |
|
|
"protectedTitleCache",
|
84 |
|
|
"rights",
|
85 |
|
|
"extensions",
|
86 |
db45aff9
|
Andreas Müller
|
"credits",
|
87 |
70440a7d
|
a.babadshanjan
|
"sources"
|
88 |
|
|
})
|
89 |
a13c5f66
|
Andreas Müller
|
@Audited
|
90 |
9479da48
|
Andreas Müller
|
@MappedSuperclass
|
91 |
22a09e94
|
Andreas Kohlbecker
|
public abstract class IdentifiableEntity<S extends IIdentifiableEntityCacheStrategy> extends AnnotatableEntity
|
92 |
|
|
implements IIdentifiableEntity /*, ISourceable<IdentifiableSource> */ {
|
93 |
|
|
private static final long serialVersionUID = -5610995424730659058L;
|
94 |
|
|
private static final Logger logger = Logger.getLogger(IdentifiableEntity.class);
|
95 |
|
|
|
96 |
|
|
@XmlTransient
|
97 |
|
|
public static final boolean PROTECTED = true;
|
98 |
|
|
@XmlTransient
|
99 |
|
|
public static final boolean NOT_PROTECTED = false;
|
100 |
|
|
|
101 |
|
|
@XmlElement(name = "LSID", type = String.class)
|
102 |
|
|
@XmlJavaTypeAdapter(LSIDAdapter.class)
|
103 |
|
|
@Embedded
|
104 |
|
|
private LSID lsid;
|
105 |
|
|
|
106 |
|
|
@XmlElement(name = "TitleCache", required = true)
|
107 |
|
|
@XmlJavaTypeAdapter(FormattedTextAdapter.class)
|
108 |
|
|
@Column(length=255, name="titleCache")
|
109 |
|
|
@Match(value=MatchMode.CACHE, cacheReplaceMode=ReplaceMode.ALL)
|
110 |
|
|
@NotEmpty(groups = Level2.class) // implictly NotNull
|
111 |
6c6108d4
|
Andreas Müller
|
@Size(max = 800) //see #1592
|
112 |
ac1a821b
|
Andreas Kohlbecker
|
@Fields({
|
113 |
|
|
@Field(store=Store.YES),
|
114 |
4af7bea2
|
Andreas Kohlbecker
|
@Field(name = "titleCache__sort", analyze = Analyze.NO, store=Store.YES)
|
115 |
ac1a821b
|
Andreas Kohlbecker
|
})
|
116 |
0930d1c2
|
Andreas Kohlbecker
|
@FieldBridge(impl=StripHtmlBridge.class)
|
117 |
22a09e94
|
Andreas Kohlbecker
|
protected String titleCache;
|
118 |
|
|
|
119 |
|
|
//if true titleCache will not be automatically generated/updated
|
120 |
|
|
@XmlElement(name = "ProtectedTitleCache")
|
121 |
|
|
protected boolean protectedTitleCache;
|
122 |
|
|
|
123 |
a784f00f
|
Katja Luther
|
@XmlElementWrapper(name = "Rights", nillable = true)
|
124 |
b2c5e42e
|
em.lee
|
@XmlElement(name = "Rights")
|
125 |
95d79c4d
|
Andreas Müller
|
@OneToMany(fetch = FetchType.LAZY, orphanRemoval=true)
|
126 |
|
|
@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
|
127 |
22a09e94
|
Andreas Kohlbecker
|
//TODO
|
128 |
|
|
@Merge(MergeMode.ADD_CLONE)
|
129 |
|
|
@NotNull
|
130 |
|
|
private Set<Rights> rights = new HashSet<Rights>();
|
131 |
|
|
|
132 |
a784f00f
|
Katja Luther
|
@XmlElementWrapper(name = "Credits", nillable = true)
|
133 |
b2c5e42e
|
em.lee
|
@XmlElement(name = "Credit")
|
134 |
db45aff9
|
Andreas Müller
|
@IndexColumn(name="sortIndex", base = 0)
|
135 |
95d79c4d
|
Andreas Müller
|
@OneToMany(fetch = FetchType.LAZY, orphanRemoval=true)
|
136 |
|
|
@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
|
137 |
53befb32
|
Andreas Müller
|
//TODO
|
138 |
22a09e94
|
Andreas Kohlbecker
|
@Merge(MergeMode.ADD_CLONE)
|
139 |
|
|
@NotNull
|
140 |
|
|
private List<Credit> credits = new ArrayList<Credit>();
|
141 |
|
|
|
142 |
a784f00f
|
Katja Luther
|
@XmlElementWrapper(name = "Extensions", nillable = true)
|
143 |
b2c5e42e
|
em.lee
|
@XmlElement(name = "Extension")
|
144 |
95d79c4d
|
Andreas Müller
|
@OneToMany(fetch = FetchType.LAZY, orphanRemoval=true)
|
145 |
|
|
@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
|
146 |
22a09e94
|
Andreas Kohlbecker
|
@Merge(MergeMode.ADD_CLONE)
|
147 |
|
|
@NotNull
|
148 |
|
|
private Set<Extension> extensions = new HashSet<Extension>();
|
149 |
|
|
|
150 |
a784f00f
|
Katja Luther
|
@XmlElementWrapper(name = "Sources", nillable = true)
|
151 |
ece46ca8
|
Andreas Kohlbecker
|
@XmlElement(name = "IdentifiableSource")
|
152 |
95d79c4d
|
Andreas Müller
|
@OneToMany(fetch = FetchType.LAZY, orphanRemoval=true)
|
153 |
|
|
@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
|
154 |
22a09e94
|
Andreas Kohlbecker
|
@Merge(MergeMode.ADD_CLONE)
|
155 |
|
|
@NotNull
|
156 |
|
|
private Set<IdentifiableSource> sources = new HashSet<IdentifiableSource>();
|
157 |
|
|
|
158 |
4208745a
|
ben.clark
|
@XmlTransient
|
159 |
22a09e94
|
Andreas Kohlbecker
|
@Transient
|
160 |
|
|
protected S cacheStrategy;
|
161 |
|
|
|
162 |
5ea47892
|
Andreas Müller
|
protected IdentifiableEntity(){
|
163 |
22a09e94
|
Andreas Kohlbecker
|
initListener();
|
164 |
a48d5a59
|
Andreas Müller
|
}
|
165 |
22a09e94
|
Andreas Kohlbecker
|
|
166 |
a48d5a59
|
Andreas Müller
|
protected void initListener(){
|
167 |
22a09e94
|
Andreas Kohlbecker
|
PropertyChangeListener listener = new PropertyChangeListener() {
|
168 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
169 |
f71ee1b8
|
Andreas Kohlbecker
|
public void propertyChange(PropertyChangeEvent e) {
|
170 |
22a09e94
|
Andreas Kohlbecker
|
if (!e.getPropertyName().equals("titleCache") && !e.getPropertyName().equals("cacheStrategy") && ! isProtectedTitleCache()){
|
171 |
|
|
titleCache = null;
|
172 |
|
|
}
|
173 |
|
|
}
|
174 |
|
|
};
|
175 |
|
|
addPropertyChangeListener(listener);
|
176 |
|
|
}
|
177 |
|
|
|
178 |
|
|
/**
|
179 |
|
|
* By default, we expect most cdm objects to be abstract things
|
180 |
|
|
* i.e. unable to return a data representation.
|
181 |
|
|
*
|
182 |
|
|
* Specific subclasses (e.g. Sequence) can override if necessary.
|
183 |
|
|
*/
|
184 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
185 |
f71ee1b8
|
Andreas Kohlbecker
|
public byte[] getData() {
|
186 |
22a09e94
|
Andreas Kohlbecker
|
return null;
|
187 |
|
|
}
|
188 |
|
|
|
189 |
|
|
//******************************** CACHE *****************************************************/
|
190 |
|
|
|
191 |
|
|
|
192 |
|
|
/* (non-Javadoc)
|
193 |
|
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#getTitleCache()
|
194 |
|
|
*/
|
195 |
|
|
// @Transient - must not be transient, since this property needs to to be included in all serializations produced by the remote layer
|
196 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
197 |
f71ee1b8
|
Andreas Kohlbecker
|
public String getTitleCache(){
|
198 |
22a09e94
|
Andreas Kohlbecker
|
if (protectedTitleCache){
|
199 |
|
|
return this.titleCache;
|
200 |
|
|
}
|
201 |
|
|
// is title dirty, i.e. equal NULL?
|
202 |
|
|
if (titleCache == null){
|
203 |
|
|
this.titleCache = generateTitle();
|
204 |
|
|
this.titleCache = getTruncatedCache(this.titleCache) ;
|
205 |
|
|
}
|
206 |
|
|
return titleCache;
|
207 |
|
|
}
|
208 |
f71ee1b8
|
Andreas Kohlbecker
|
|
209 |
ba03c965
|
Patric Plitzner
|
/**
|
210 |
cc2ec4e9
|
Andreas Kohlbecker
|
* The titleCache will be regenerated from scratch if not protected
|
211 |
|
|
* @return <code>true</code> if title cache was regenerated, <code>false</code> otherwise
|
212 |
ba03c965
|
Patric Plitzner
|
*/
|
213 |
f71ee1b8
|
Andreas Kohlbecker
|
protected boolean regenerateTitleCache() {
|
214 |
|
|
if (!protectedTitleCache) {
|
215 |
|
|
this.titleCache = null;
|
216 |
|
|
getTitleCache();
|
217 |
|
|
}
|
218 |
|
|
return protectedTitleCache;
|
219 |
|
|
}
|
220 |
87cab9c5
|
Andreas Müller
|
|
221 |
|
|
@Deprecated
|
222 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
223 |
f71ee1b8
|
Andreas Kohlbecker
|
public void setTitleCache(String titleCache){
|
224 |
79ca3e43
|
Andreas Müller
|
//TODO shouldn't we call setTitleCache(String, boolean),but is this conformant with Java Bean Specification?
|
225 |
|
|
this.titleCache = getTruncatedCache(titleCache);
|
226 |
22a09e94
|
Andreas Kohlbecker
|
}
|
227 |
|
|
|
228 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
229 |
f71ee1b8
|
Andreas Kohlbecker
|
public void setTitleCache(String titleCache, boolean protectCache){
|
230 |
22a09e94
|
Andreas Kohlbecker
|
titleCache = getTruncatedCache(titleCache);
|
231 |
|
|
this.titleCache = titleCache;
|
232 |
|
|
this.protectedTitleCache = protectCache;
|
233 |
|
|
}
|
234 |
|
|
|
235 |
|
|
|
236 |
|
|
/**
|
237 |
|
|
* @param cache
|
238 |
|
|
* @return
|
239 |
|
|
*/
|
240 |
|
|
@Transient
|
241 |
|
|
protected String getTruncatedCache(String cache) {
|
242 |
79ca3e43
|
Andreas Müller
|
int maxLength = 800;
|
243 |
|
|
if (cache != null && cache.length() > maxLength){
|
244 |
22a09e94
|
Andreas Kohlbecker
|
logger.warn("Truncation of cache: " + this.toString() + "/" + cache);
|
245 |
79ca3e43
|
Andreas Müller
|
cache = cache.substring(0, maxLength - 4) + "..."; //TODO do we need -4 or is -3 enough
|
246 |
22a09e94
|
Andreas Kohlbecker
|
}
|
247 |
|
|
return cache;
|
248 |
5ea47892
|
Andreas Müller
|
}
|
249 |
9479da48
|
Andreas Müller
|
|
250 |
3b1a8846
|
Andreas Müller
|
//**************************************************************************************
|
251 |
22a09e94
|
Andreas Kohlbecker
|
|
252 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
253 |
f71ee1b8
|
Andreas Kohlbecker
|
public LSID getLsid(){
|
254 |
22a09e94
|
Andreas Kohlbecker
|
return this.lsid;
|
255 |
|
|
}
|
256 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
257 |
f71ee1b8
|
Andreas Kohlbecker
|
public void setLsid(LSID lsid){
|
258 |
22a09e94
|
Andreas Kohlbecker
|
this.lsid = lsid;
|
259 |
|
|
}
|
260 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
261 |
f71ee1b8
|
Andreas Kohlbecker
|
public Set<Rights> getRights() {
|
262 |
22a09e94
|
Andreas Kohlbecker
|
if(rights == null) {
|
263 |
|
|
this.rights = new HashSet<Rights>();
|
264 |
|
|
}
|
265 |
|
|
return this.rights;
|
266 |
|
|
}
|
267 |
|
|
|
268 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
269 |
f71ee1b8
|
Andreas Kohlbecker
|
public void addRights(Rights right){
|
270 |
22a09e94
|
Andreas Kohlbecker
|
getRights().add(right);
|
271 |
|
|
}
|
272 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
273 |
f71ee1b8
|
Andreas Kohlbecker
|
public void removeRights(Rights right){
|
274 |
22a09e94
|
Andreas Kohlbecker
|
getRights().remove(right);
|
275 |
|
|
}
|
276 |
|
|
|
277 |
|
|
|
278 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
279 |
f71ee1b8
|
Andreas Kohlbecker
|
public List<Credit> getCredits() {
|
280 |
22a09e94
|
Andreas Kohlbecker
|
if(credits == null) {
|
281 |
|
|
this.credits = new ArrayList<Credit>();
|
282 |
|
|
}
|
283 |
|
|
return this.credits;
|
284 |
|
|
}
|
285 |
|
|
|
286 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
287 |
f71ee1b8
|
Andreas Kohlbecker
|
public Credit getCredits(Integer index){
|
288 |
22a09e94
|
Andreas Kohlbecker
|
return getCredits().get(index);
|
289 |
|
|
}
|
290 |
|
|
|
291 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
292 |
f71ee1b8
|
Andreas Kohlbecker
|
public void addCredit(Credit credit){
|
293 |
22a09e94
|
Andreas Kohlbecker
|
getCredits().add(credit);
|
294 |
|
|
}
|
295 |
|
|
|
296 |
|
|
|
297 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
298 |
f71ee1b8
|
Andreas Kohlbecker
|
public void addCredit(Credit credit, int index){
|
299 |
22a09e94
|
Andreas Kohlbecker
|
getCredits().add(index, credit);
|
300 |
|
|
}
|
301 |
|
|
|
302 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
303 |
f71ee1b8
|
Andreas Kohlbecker
|
public void removeCredit(Credit credit){
|
304 |
22a09e94
|
Andreas Kohlbecker
|
getCredits().remove(credit);
|
305 |
|
|
}
|
306 |
|
|
|
307 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
308 |
f71ee1b8
|
Andreas Kohlbecker
|
public void removeCredit(int index){
|
309 |
22a09e94
|
Andreas Kohlbecker
|
getCredits().remove(index);
|
310 |
|
|
}
|
311 |
|
|
|
312 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
313 |
f71ee1b8
|
Andreas Kohlbecker
|
public Set<Extension> getExtensions(){
|
314 |
22a09e94
|
Andreas Kohlbecker
|
if(extensions == null) {
|
315 |
|
|
this.extensions = new HashSet<Extension>();
|
316 |
|
|
}
|
317 |
|
|
return this.extensions;
|
318 |
|
|
}
|
319 |
f71ee1b8
|
Andreas Kohlbecker
|
/**
|
320 |
|
|
* @param type
|
321 |
|
|
* @return a Set of extension value strings
|
322 |
|
|
*/
|
323 |
43b314ef
|
Andreas Müller
|
public Set<String> getExtensions(ExtensionType type){
|
324 |
|
|
return getExtensions(type.getUuid());
|
325 |
|
|
}
|
326 |
f71ee1b8
|
Andreas Kohlbecker
|
/**
|
327 |
|
|
* @param extensionTypeUuid
|
328 |
|
|
* @return a Set of extension value strings
|
329 |
|
|
*/
|
330 |
43b314ef
|
Andreas Müller
|
public Set<String> getExtensions(UUID extensionTypeUuid){
|
331 |
0930d1c2
|
Andreas Kohlbecker
|
Set<String> result = new HashSet<String>();
|
332 |
|
|
for (Extension extension : getExtensions()){
|
333 |
|
|
if (extension.getType().getUuid().equals(extensionTypeUuid)){
|
334 |
|
|
result.add(extension.getValue());
|
335 |
|
|
}
|
336 |
|
|
}
|
337 |
43b314ef
|
Andreas Müller
|
return result;
|
338 |
|
|
}
|
339 |
22a09e94
|
Andreas Kohlbecker
|
|
340 |
|
|
public void addExtension(String value, ExtensionType extensionType){
|
341 |
|
|
Extension.NewInstance(this, value, extensionType);
|
342 |
|
|
}
|
343 |
|
|
|
344 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
345 |
f71ee1b8
|
Andreas Kohlbecker
|
public void addExtension(Extension extension){
|
346 |
22a09e94
|
Andreas Kohlbecker
|
if (extension != null){
|
347 |
|
|
extension.setExtendedObj(this);
|
348 |
|
|
getExtensions().add(extension);
|
349 |
|
|
}
|
350 |
|
|
}
|
351 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
352 |
f71ee1b8
|
Andreas Kohlbecker
|
public void removeExtension(Extension extension){
|
353 |
22a09e94
|
Andreas Kohlbecker
|
if (extension != null){
|
354 |
|
|
extension.setExtendedObj(null);
|
355 |
|
|
getExtensions().remove(extension);
|
356 |
|
|
}
|
357 |
|
|
}
|
358 |
|
|
|
359 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
360 |
f71ee1b8
|
Andreas Kohlbecker
|
public boolean isProtectedTitleCache() {
|
361 |
22a09e94
|
Andreas Kohlbecker
|
return protectedTitleCache;
|
362 |
|
|
}
|
363 |
|
|
|
364 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
365 |
f71ee1b8
|
Andreas Kohlbecker
|
public void setProtectedTitleCache(boolean protectedTitleCache) {
|
366 |
22a09e94
|
Andreas Kohlbecker
|
this.protectedTitleCache = protectedTitleCache;
|
367 |
|
|
}
|
368 |
|
|
|
369 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
370 |
f71ee1b8
|
Andreas Kohlbecker
|
public Set<IdentifiableSource> getSources() {
|
371 |
22a09e94
|
Andreas Kohlbecker
|
if(sources == null) {
|
372 |
|
|
this.sources = new HashSet<IdentifiableSource>();
|
373 |
|
|
}
|
374 |
|
|
return this.sources;
|
375 |
|
|
}
|
376 |
|
|
|
377 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
378 |
f71ee1b8
|
Andreas Kohlbecker
|
public void addSource(IdentifiableSource source) {
|
379 |
22a09e94
|
Andreas Kohlbecker
|
if (source != null){
|
380 |
e28e4b81
|
Andreas Müller
|
IdentifiableEntity<?> oldSourcedObj = source.getSourcedObj();
|
381 |
22a09e94
|
Andreas Kohlbecker
|
if (oldSourcedObj != null && oldSourcedObj != this){
|
382 |
|
|
oldSourcedObj.getSources().remove(source);
|
383 |
|
|
}
|
384 |
|
|
getSources().add(source);
|
385 |
|
|
source.setSourcedObj(this);
|
386 |
|
|
}
|
387 |
|
|
}
|
388 |
|
|
|
389 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
390 |
fad74844
|
Andreas Müller
|
public IdentifiableSource addSource(OriginalSourceType type, String id, String idNamespace, Reference citation, String microCitation) {
|
391 |
22a09e94
|
Andreas Kohlbecker
|
if (id == null && idNamespace == null && citation == null && microCitation == null){
|
392 |
|
|
return null;
|
393 |
|
|
}
|
394 |
fad74844
|
Andreas Müller
|
IdentifiableSource source = IdentifiableSource.NewInstance(type, id, idNamespace, citation, microCitation);
|
395 |
|
|
addSource(source);
|
396 |
|
|
return source;
|
397 |
|
|
}
|
398 |
|
|
|
399 |
|
|
|
400 |
|
|
@Override
|
401 |
|
|
public IdentifiableSource addImportSource(String id, String idNamespace, Reference<?> citation, String microCitation) {
|
402 |
|
|
if (id == null && idNamespace == null && citation == null && microCitation == null){
|
403 |
|
|
return null;
|
404 |
|
|
}
|
405 |
|
|
IdentifiableSource source = IdentifiableSource.NewInstance(OriginalSourceType.Import, id, idNamespace, citation, microCitation);
|
406 |
22a09e94
|
Andreas Kohlbecker
|
addSource(source);
|
407 |
|
|
return source;
|
408 |
|
|
}
|
409 |
|
|
|
410 |
e28e4b81
|
Andreas Müller
|
|
411 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
412 |
f71ee1b8
|
Andreas Kohlbecker
|
public void removeSource(IdentifiableSource source) {
|
413 |
22a09e94
|
Andreas Kohlbecker
|
getSources().remove(source);
|
414 |
|
|
}
|
415 |
|
|
|
416 |
|
|
//******************************** TO STRING *****************************************************/
|
417 |
|
|
|
418 |
|
|
/* (non-Javadoc)
|
419 |
|
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#toString()
|
420 |
|
|
*/
|
421 |
|
|
@Override
|
422 |
|
|
public String toString() {
|
423 |
|
|
String result;
|
424 |
|
|
if (titleCache == null){
|
425 |
|
|
result = super.toString();
|
426 |
|
|
}else{
|
427 |
|
|
result = this.titleCache;
|
428 |
|
|
}
|
429 |
|
|
return result;
|
430 |
|
|
}
|
431 |
|
|
|
432 |
|
|
|
433 |
|
|
public int compareTo(IdentifiableEntity identifiableEntity) {
|
434 |
|
|
|
435 |
|
|
int result = 0;
|
436 |
|
|
|
437 |
|
|
if (identifiableEntity == null) {
|
438 |
|
|
throw new NullPointerException("Cannot compare to null.");
|
439 |
|
|
}
|
440 |
|
|
|
441 |
|
|
// First, compare the name cache.
|
442 |
|
|
// TODO: Avoid using instanceof operator
|
443 |
|
|
// Use Class.getDeclaredMethod() instead to find out whether class has getNameCache() method?
|
444 |
|
|
|
445 |
|
|
String specifiedNameCache = "";
|
446 |
|
|
String thisNameCache = "";
|
447 |
|
|
String specifiedTitleCache = "";
|
448 |
|
|
String thisTitleCache = "";
|
449 |
|
|
String specifiedReferenceTitleCache = "";
|
450 |
|
|
String thisReferenceTitleCache = "";
|
451 |
|
|
String thisGenusString = "";
|
452 |
|
|
String specifiedGenusString = "";
|
453 |
|
|
int thisrank_order = 0;
|
454 |
|
|
|
455 |
f6de71b0
|
Andreas Müller
|
//TODO we can remove all the deproxies here except for the first one
|
456 |
|
|
identifiableEntity = HibernateProxyHelper.deproxy(identifiableEntity, IdentifiableEntity.class);
|
457 |
22a09e94
|
Andreas Kohlbecker
|
if(identifiableEntity instanceof NonViralName) {
|
458 |
|
|
specifiedNameCache = HibernateProxyHelper.deproxy(identifiableEntity, NonViralName.class).getNameCache();
|
459 |
|
|
specifiedTitleCache = identifiableEntity.getTitleCache();
|
460 |
3b98b0db
|
Katja Luther
|
if (identifiableEntity instanceof BotanicalName){
|
461 |
|
|
if (((BotanicalName)identifiableEntity).isAutonym()){
|
462 |
|
|
boolean isProtected = false;
|
463 |
|
|
String oldNameCache = ((BotanicalName) identifiableEntity).getNameCache();
|
464 |
|
|
if ( ((BotanicalName)identifiableEntity).isProtectedNameCache()){
|
465 |
|
|
isProtected = true;
|
466 |
|
|
}
|
467 |
|
|
((BotanicalName)identifiableEntity).setProtectedNameCache(false);
|
468 |
|
|
((BotanicalName)identifiableEntity).setNameCache(null, false);
|
469 |
|
|
specifiedNameCache = ((BotanicalName) identifiableEntity).getNameCache();
|
470 |
|
|
((BotanicalName)identifiableEntity).setNameCache(oldNameCache, isProtected);
|
471 |
|
|
|
472 |
|
|
}
|
473 |
|
|
}
|
474 |
22a09e94
|
Andreas Kohlbecker
|
|
475 |
|
|
} else if(identifiableEntity instanceof TaxonBase) {
|
476 |
|
|
TaxonBase taxonBase = HibernateProxyHelper.deproxy(identifiableEntity, TaxonBase.class);
|
477 |
|
|
|
478 |
|
|
TaxonNameBase<?,?> taxonNameBase = taxonBase.getName();
|
479 |
|
|
|
480 |
|
|
|
481 |
|
|
NonViralName nonViralName = HibernateProxyHelper.deproxy(taxonNameBase, NonViralName.class);
|
482 |
|
|
specifiedNameCache = nonViralName.getNameCache();
|
483 |
|
|
specifiedTitleCache = taxonNameBase.getTitleCache();
|
484 |
|
|
|
485 |
|
|
specifiedReferenceTitleCache = ((TaxonBase)identifiableEntity).getSec().getTitleCache();
|
486 |
|
|
Reference reference = taxonBase.getSec();
|
487 |
|
|
if (reference != null) {
|
488 |
|
|
reference = HibernateProxyHelper.deproxy(reference, Reference.class);
|
489 |
|
|
specifiedReferenceTitleCache = reference.getTitleCache();
|
490 |
|
|
}
|
491 |
|
|
}
|
492 |
|
|
|
493 |
84938015
|
Andreas Müller
|
if(this.isInstanceOf(NonViralName.class)) {
|
494 |
22a09e94
|
Andreas Kohlbecker
|
thisNameCache = HibernateProxyHelper.deproxy(this, NonViralName.class).getNameCache();
|
495 |
|
|
thisTitleCache = getTitleCache();
|
496 |
3b98b0db
|
Katja Luther
|
|
497 |
|
|
if (this instanceof BotanicalName){
|
498 |
|
|
if (((BotanicalName)this).isAutonym()){
|
499 |
|
|
boolean isProtected = false;
|
500 |
|
|
String oldNameCache = ((BotanicalName) this).getNameCache();
|
501 |
|
|
if ( ((BotanicalName)this).isProtectedNameCache()){
|
502 |
|
|
isProtected = true;
|
503 |
|
|
}
|
504 |
|
|
((BotanicalName)this).setProtectedNameCache(false);
|
505 |
|
|
((BotanicalName)this).setNameCache(null, false);
|
506 |
|
|
thisNameCache = ((BotanicalName) this).getNameCache();
|
507 |
|
|
((BotanicalName)this).setNameCache(oldNameCache, isProtected);
|
508 |
|
|
}
|
509 |
|
|
}
|
510 |
84938015
|
Andreas Müller
|
} else if(this.isInstanceOf(TaxonBase.class)) {
|
511 |
22a09e94
|
Andreas Kohlbecker
|
TaxonNameBase<?,?> taxonNameBase= HibernateProxyHelper.deproxy(this, TaxonBase.class).getName();
|
512 |
|
|
NonViralName nonViralName = HibernateProxyHelper.deproxy(taxonNameBase, NonViralName.class);
|
513 |
|
|
thisNameCache = nonViralName.getNameCache();
|
514 |
|
|
thisTitleCache = taxonNameBase.getTitleCache();
|
515 |
0f24bfe5
|
Katja Luther
|
thisReferenceTitleCache = ((TaxonBase)this).getSec().getTitleCache();
|
516 |
22a09e94
|
Andreas Kohlbecker
|
thisGenusString = nonViralName.getGenusOrUninomial();
|
517 |
|
|
}
|
518 |
|
|
|
519 |
|
|
// Compare name cache of taxon names
|
520 |
3b98b0db
|
Katja Luther
|
|
521 |
|
|
|
522 |
22a09e94
|
Andreas Kohlbecker
|
|
523 |
|
|
if (!specifiedNameCache.equals("") && !thisNameCache.equals("")) {
|
524 |
|
|
result = thisNameCache.compareTo(specifiedNameCache);
|
525 |
|
|
}
|
526 |
|
|
|
527 |
|
|
// Compare title cache of taxon names
|
528 |
|
|
|
529 |
|
|
if ((result == 0) && (!specifiedTitleCache.equals("") || !thisTitleCache.equals(""))) {
|
530 |
|
|
result = thisTitleCache.compareTo(specifiedTitleCache);
|
531 |
|
|
}
|
532 |
|
|
|
533 |
|
|
// Compare title cache of taxon references
|
534 |
|
|
|
535 |
|
|
if ((result == 0) && (!specifiedReferenceTitleCache.equals("") || !thisReferenceTitleCache.equals(""))) {
|
536 |
|
|
result = thisReferenceTitleCache.compareTo(specifiedReferenceTitleCache);
|
537 |
|
|
}
|
538 |
|
|
|
539 |
|
|
return result;
|
540 |
|
|
}
|
541 |
|
|
|
542 |
|
|
/**
|
543 |
|
|
* Returns the {@link eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy cache strategy} used to generate
|
544 |
|
|
* several strings corresponding to <i>this</i> identifiable entity
|
545 |
|
|
* (in particular taxon name caches and author strings).
|
546 |
|
|
*
|
547 |
|
|
* @return the cache strategy used for <i>this</i> identifiable entity
|
548 |
|
|
* @see eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy
|
549 |
|
|
*/
|
550 |
|
|
public S getCacheStrategy() {
|
551 |
|
|
return this.cacheStrategy;
|
552 |
|
|
}
|
553 |
|
|
/**
|
554 |
|
|
* @see #getCacheStrategy()
|
555 |
|
|
*/
|
556 |
|
|
|
557 |
|
|
public void setCacheStrategy(S cacheStrategy) {
|
558 |
|
|
this.cacheStrategy = cacheStrategy;
|
559 |
|
|
}
|
560 |
|
|
|
561 |
cc2ec4e9
|
Andreas Kohlbecker
|
@Override
|
562 |
f71ee1b8
|
Andreas Kohlbecker
|
public String generateTitle() {
|
563 |
60d8ad91
|
Andreas Müller
|
if (getCacheStrategy() == null){
|
564 |
22a09e94
|
Andreas Kohlbecker
|
//logger.warn("No CacheStrategy defined for "+ this.getClass() + ": " + this.getUuid());
|
565 |
|
|
return this.getClass() + ": " + this.getUuid();
|
566 |
|
|
}else{
|
567 |
60d8ad91
|
Andreas Müller
|
return getCacheStrategy().getTitleCache(this);
|
568 |
22a09e94
|
Andreas Kohlbecker
|
}
|
569 |
|
|
}
|
570 |
|
|
|
571 |
835c12dd
|
Andreas Müller
|
//****************** CLONE ************************************************/
|
572 |
22a09e94
|
Andreas Kohlbecker
|
|
573 |
|
|
/* (non-Javadoc)
|
574 |
|
|
* @see eu.etaxonomy.cdm.model.common.AnnotatableEntity#clone()
|
575 |
|
|
*/
|
576 |
|
|
@Override
|
577 |
|
|
public Object clone() throws CloneNotSupportedException{
|
578 |
|
|
IdentifiableEntity result = (IdentifiableEntity)super.clone();
|
579 |
|
|
|
580 |
|
|
//Extensions
|
581 |
|
|
result.extensions = new HashSet<Extension>();
|
582 |
|
|
for (Extension extension : getExtensions() ){
|
583 |
|
|
Extension newExtension = (Extension)extension.clone();
|
584 |
|
|
result.addExtension(newExtension);
|
585 |
|
|
}
|
586 |
|
|
|
587 |
|
|
//OriginalSources
|
588 |
|
|
result.sources = new HashSet<IdentifiableSource>();
|
589 |
|
|
for (IdentifiableSource source : getSources()){
|
590 |
|
|
IdentifiableSource newSource = (IdentifiableSource)source.clone();
|
591 |
|
|
result.addSource(newSource);
|
592 |
|
|
}
|
593 |
|
|
|
594 |
|
|
//Rights
|
595 |
|
|
result.rights = new HashSet<Rights>();
|
596 |
a784f00f
|
Katja Luther
|
for(Rights rights : getRights()) {
|
597 |
22a09e94
|
Andreas Kohlbecker
|
result.addRights(rights);
|
598 |
ee91bcd9
|
ben.clark
|
}
|
599 |
57ea5ac1
|
Andreas Müller
|
|
600 |
22a09e94
|
Andreas Kohlbecker
|
|
601 |
|
|
//Credits
|
602 |
|
|
result.credits = new ArrayList<Credit>();
|
603 |
a784f00f
|
Katja Luther
|
for(Credit credit : getCredits()) {
|
604 |
22a09e94
|
Andreas Kohlbecker
|
result.addCredit(credit);
|
605 |
57ea5ac1
|
Andreas Müller
|
}
|
606 |
|
|
|
607 |
22a09e94
|
Andreas Kohlbecker
|
//no changes to: lsid, titleCache, protectedTitleCache
|
608 |
|
|
|
609 |
|
|
//empty titleCache
|
610 |
|
|
if (! protectedTitleCache){
|
611 |
|
|
result.titleCache = null;
|
612 |
|
|
}
|
613 |
|
|
|
614 |
|
|
result.initListener();
|
615 |
|
|
return result;
|
616 |
|
|
}
|
617 |
|
|
|
618 |
53befb32
|
Andreas Müller
|
|
619 |
9479da48
|
Andreas Müller
|
}
|