1
|
/**
|
2
|
* Copyright (C) 2007 EDIT
|
3
|
* European Distributed Institute of Taxonomy
|
4
|
* http://www.e-taxonomy.eu
|
5
|
*
|
6
|
* 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
|
import java.util.HashSet;
|
14
|
import java.util.Set;
|
15
|
|
16
|
import javax.persistence.Column;
|
17
|
import javax.persistence.ManyToMany;
|
18
|
import javax.persistence.MappedSuperclass;
|
19
|
import javax.persistence.OneToMany;
|
20
|
import javax.persistence.Transient;
|
21
|
import javax.xml.bind.annotation.XmlAccessType;
|
22
|
import javax.xml.bind.annotation.XmlAccessorType;
|
23
|
import javax.xml.bind.annotation.XmlElement;
|
24
|
import javax.xml.bind.annotation.XmlElementWrapper;
|
25
|
import javax.xml.bind.annotation.XmlTransient;
|
26
|
import javax.xml.bind.annotation.XmlType;
|
27
|
|
28
|
import org.apache.log4j.Logger;
|
29
|
import org.hibernate.annotations.Cascade;
|
30
|
import org.hibernate.annotations.CascadeType;
|
31
|
|
32
|
import eu.etaxonomy.cdm.model.media.Rights;
|
33
|
|
34
|
/**
|
35
|
* 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.
|
36
|
* All subclasses inherit the ability to store additional properties that are stored as {@link Extension Extensions}, basically a string value with a type term.
|
37
|
* Any number of right statements can be attached as well as multiple {@link OriginalSource} objects.
|
38
|
* 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).
|
39
|
* A Taxon for example that was taken from 2 sources like FaunaEuropaea and IPNI would have two originalSource objects.
|
40
|
* 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.
|
41
|
*
|
42
|
* @author m.doering
|
43
|
* @version 1.0
|
44
|
* @created 08-Nov-2007 13:06:27
|
45
|
*/
|
46
|
@XmlAccessorType(XmlAccessType.FIELD)
|
47
|
@XmlType(name = "IdentifiableEntity", propOrder = {
|
48
|
"lsid",
|
49
|
"titleCache",
|
50
|
"protectedTitleCache",
|
51
|
"rights",
|
52
|
"extensions",
|
53
|
"sources"
|
54
|
})
|
55
|
@MappedSuperclass
|
56
|
public abstract class IdentifiableEntity<T extends IdentifiableEntity> extends AnnotatableEntity<T> implements ISourceable, IIdentifiableEntity<T> {
|
57
|
private static final Logger logger = Logger.getLogger(IdentifiableEntity.class);
|
58
|
|
59
|
@XmlTransient
|
60
|
public final boolean PROTECTED = true;
|
61
|
@XmlTransient
|
62
|
public final boolean NOT_PROTECTED = false;
|
63
|
|
64
|
@XmlElement(name = "LSID")
|
65
|
private String lsid;
|
66
|
|
67
|
@XmlElement(name = "TitleCache", required = true)
|
68
|
private String titleCache;
|
69
|
|
70
|
//if true titleCache will not be automatically generated/updated
|
71
|
@XmlElement(name = "ProtectedTitleCache")
|
72
|
private boolean protectedTitleCache;
|
73
|
|
74
|
@XmlElementWrapper(name = "Rights")
|
75
|
@XmlElement(name = "Rights")
|
76
|
private Set<Rights> rights = getNewRightsSet();
|
77
|
|
78
|
@XmlElementWrapper(name = "Extensions")
|
79
|
@XmlElement(name = "Extension")
|
80
|
private Set<Extension> extensions = getNewExtensionSet();
|
81
|
|
82
|
@XmlElementWrapper(name = "Sources")
|
83
|
@XmlElement(name = "OriginalSource")
|
84
|
private Set<OriginalSource> sources = getNewOriginalSourcesSet();
|
85
|
|
86
|
|
87
|
/* (non-Javadoc)
|
88
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#getLsid()
|
89
|
*/
|
90
|
public String getLsid(){
|
91
|
return this.lsid;
|
92
|
}
|
93
|
/* (non-Javadoc)
|
94
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#setLsid(java.lang.String)
|
95
|
*/
|
96
|
public void setLsid(String lsid){
|
97
|
this.lsid = lsid;
|
98
|
}
|
99
|
|
100
|
/* (non-Javadoc)
|
101
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#generateTitle()
|
102
|
*/
|
103
|
public abstract String generateTitle();
|
104
|
|
105
|
/* (non-Javadoc)
|
106
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#getTitleCache()
|
107
|
*/
|
108
|
@Transient
|
109
|
public String getTitleCache(){
|
110
|
if (protectedTitleCache){
|
111
|
return this.titleCache;
|
112
|
}
|
113
|
// is title dirty, i.e. equal NULL?
|
114
|
if (titleCache == null){
|
115
|
this.setTitleCache(generateTitle(),protectedTitleCache) ; //for truncating
|
116
|
}
|
117
|
return titleCache;
|
118
|
}
|
119
|
/* (non-Javadoc)
|
120
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#setTitleCache(java.lang.String)
|
121
|
*/
|
122
|
public void setTitleCache(String titleCache){
|
123
|
setTitleCache(titleCache, PROTECTED);
|
124
|
}
|
125
|
|
126
|
//@Index(name="titleCacheIndex")
|
127
|
/* (non-Javadoc)
|
128
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#getTitleCache()
|
129
|
*/
|
130
|
@Column(length=255, name="titleCache")
|
131
|
@Deprecated //for hibernate use only
|
132
|
protected String getPersistentTitleCache(){
|
133
|
return getTitleCache();
|
134
|
}
|
135
|
@Deprecated //for hibernate use only
|
136
|
protected void setPersistentTitleCache(String titleCache){
|
137
|
this.titleCache = titleCache;
|
138
|
}
|
139
|
|
140
|
|
141
|
|
142
|
/* (non-Javadoc)
|
143
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#setTitleCache(java.lang.String, boolean)
|
144
|
*/
|
145
|
public void setTitleCache(String titleCache, boolean protectCache){
|
146
|
//TODO truncation of title cache
|
147
|
if (titleCache != null && titleCache.length() > 254){
|
148
|
logger.warn("Truncation of title cache: " + this.toString() + "/" + titleCache);
|
149
|
titleCache = titleCache.substring(0, 249) + "...";
|
150
|
}
|
151
|
this.titleCache = titleCache;
|
152
|
this.setProtectedTitleCache(protectCache);
|
153
|
}
|
154
|
|
155
|
/* (non-Javadoc)
|
156
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#getRights()
|
157
|
*/
|
158
|
@ManyToMany
|
159
|
@Cascade({CascadeType.SAVE_UPDATE})
|
160
|
public Set<Rights> getRights(){
|
161
|
return this.rights;
|
162
|
}
|
163
|
|
164
|
protected void setRights(Set<Rights> rights) {
|
165
|
this.rights = rights;
|
166
|
}
|
167
|
/* (non-Javadoc)
|
168
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#addRights(eu.etaxonomy.cdm.model.media.Rights)
|
169
|
*/
|
170
|
public void addRights(Rights right){
|
171
|
this.rights.add(right);
|
172
|
}
|
173
|
/* (non-Javadoc)
|
174
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#removeRights(eu.etaxonomy.cdm.model.media.Rights)
|
175
|
*/
|
176
|
public void removeRights(Rights right){
|
177
|
this.rights.remove(right);
|
178
|
}
|
179
|
|
180
|
/* (non-Javadoc)
|
181
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#getExtensions()
|
182
|
*/
|
183
|
@OneToMany//(mappedBy="extendedObj")
|
184
|
@Cascade({CascadeType.SAVE_UPDATE})
|
185
|
public Set<Extension> getExtensions(){
|
186
|
return this.extensions;
|
187
|
}
|
188
|
protected void setExtensions(Set<Extension> extensions) {
|
189
|
this.extensions = extensions;
|
190
|
}
|
191
|
/* (non-Javadoc)
|
192
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#addExtension(eu.etaxonomy.cdm.model.common.Extension)
|
193
|
*/
|
194
|
public void addExtension(Extension extension){
|
195
|
this.extensions.add(extension);
|
196
|
}
|
197
|
/* (non-Javadoc)
|
198
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#removeExtension(eu.etaxonomy.cdm.model.common.Extension)
|
199
|
*/
|
200
|
public void removeExtension(Extension extension){
|
201
|
this.extensions.remove(extension);
|
202
|
}
|
203
|
|
204
|
|
205
|
/* (non-Javadoc)
|
206
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#isProtectedTitleCache()
|
207
|
*/
|
208
|
public boolean isProtectedTitleCache() {
|
209
|
return protectedTitleCache;
|
210
|
}
|
211
|
|
212
|
/* (non-Javadoc)
|
213
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#setProtectedTitleCache(boolean)
|
214
|
*/
|
215
|
public void setProtectedTitleCache(boolean protectedTitleCache) {
|
216
|
this.protectedTitleCache = protectedTitleCache;
|
217
|
}
|
218
|
|
219
|
/* (non-Javadoc)
|
220
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#getSources()
|
221
|
*/
|
222
|
@OneToMany //(mappedBy="sourcedObj")
|
223
|
@Cascade({CascadeType.SAVE_UPDATE})
|
224
|
public Set<OriginalSource> getSources() {
|
225
|
return this.sources;
|
226
|
}
|
227
|
protected void setSources(Set<OriginalSource> sources) {
|
228
|
this.sources = sources;
|
229
|
}
|
230
|
/* (non-Javadoc)
|
231
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#addSource(eu.etaxonomy.cdm.model.common.OriginalSource)
|
232
|
*/
|
233
|
public void addSource(OriginalSource source) {
|
234
|
if (source != null){
|
235
|
IdentifiableEntity oldSourcedObj = source.getSourcedObj();
|
236
|
if (oldSourcedObj != null && oldSourcedObj != this){
|
237
|
oldSourcedObj.getSources().remove(source);
|
238
|
}
|
239
|
this.sources.add(source);
|
240
|
source.setSourcedObj(this);
|
241
|
}
|
242
|
}
|
243
|
/* (non-Javadoc)
|
244
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#removeSource(eu.etaxonomy.cdm.model.common.OriginalSource)
|
245
|
*/
|
246
|
public void removeSource(OriginalSource source) {
|
247
|
this.sources.remove(source);
|
248
|
}
|
249
|
|
250
|
/* (non-Javadoc)
|
251
|
* @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#toString()
|
252
|
*/
|
253
|
@Override
|
254
|
public String toString() {
|
255
|
String result;
|
256
|
if (titleCache == null){
|
257
|
result = super.toString();
|
258
|
}else{
|
259
|
result = this.titleCache;
|
260
|
}
|
261
|
return result;
|
262
|
}
|
263
|
|
264
|
//****************** CLONE ************************************************/
|
265
|
|
266
|
/* (non-Javadoc)
|
267
|
* @see eu.etaxonomy.cdm.model.common.AnnotatableEntity#clone()
|
268
|
*/
|
269
|
@Override
|
270
|
public Object clone() throws CloneNotSupportedException{
|
271
|
IdentifiableEntity result = (IdentifiableEntity)super.clone();
|
272
|
|
273
|
//Extensions
|
274
|
Set<Extension> newExtensions = getNewExtensionSet();
|
275
|
for (Extension extension : this.extensions ){
|
276
|
Extension newExtension = extension.clone(this);
|
277
|
newExtensions.add(newExtension);
|
278
|
}
|
279
|
result.setExtensions(newExtensions);
|
280
|
|
281
|
//OriginalSources
|
282
|
Set<OriginalSource> newOriginalSources = getNewOriginalSourcesSet();
|
283
|
for (OriginalSource originalSource : this.sources){
|
284
|
OriginalSource newSource = originalSource.clone(this);
|
285
|
newOriginalSources.add(newSource);
|
286
|
}
|
287
|
result.setSources(newOriginalSources);
|
288
|
|
289
|
//Rights
|
290
|
Set<Rights> rights = getNewRightsSet();
|
291
|
rights.addAll(this.rights);
|
292
|
result.setRights(rights);
|
293
|
|
294
|
//result.setLsid(lsid);
|
295
|
//result.setTitleCache(titleCache);
|
296
|
//result.setProtectedTitleCache(protectedTitleCache); //must be after setTitleCache
|
297
|
|
298
|
//no changes to: lsid, titleCache, protectedTitleCache
|
299
|
|
300
|
//empty titleCache
|
301
|
if (! protectedTitleCache){
|
302
|
titleCache = null;
|
303
|
}
|
304
|
return result;
|
305
|
}
|
306
|
|
307
|
@Transient
|
308
|
private Set<Extension> getNewExtensionSet(){
|
309
|
return new HashSet<Extension>();
|
310
|
}
|
311
|
|
312
|
@Transient
|
313
|
private Set<OriginalSource> getNewOriginalSourcesSet(){
|
314
|
return new HashSet<OriginalSource>();
|
315
|
}
|
316
|
|
317
|
@Transient
|
318
|
private Set<Rights> getNewRightsSet(){
|
319
|
return new HashSet<Rights>();
|
320
|
}
|
321
|
|
322
|
}
|