2 * Copyright (C) 2009 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.model
.common
;
13 import java
.util
.HashSet
;
14 import java
.util
.Iterator
;
15 import java
.util
.List
;
18 import javax
.persistence
.Column
;
19 import javax
.persistence
.FetchType
;
20 import javax
.persistence
.MappedSuperclass
;
21 import javax
.persistence
.OneToMany
;
22 import javax
.persistence
.Transient
;
23 import javax
.validation
.constraints
.NotNull
;
24 import javax
.xml
.bind
.annotation
.XmlAccessType
;
25 import javax
.xml
.bind
.annotation
.XmlAccessorType
;
26 import javax
.xml
.bind
.annotation
.XmlAttribute
;
27 import javax
.xml
.bind
.annotation
.XmlElement
;
28 import javax
.xml
.bind
.annotation
.XmlElementWrapper
;
29 import javax
.xml
.bind
.annotation
.XmlSeeAlso
;
30 import javax
.xml
.bind
.annotation
.XmlType
;
32 import org
.apache
.log4j
.Logger
;
33 import org
.hibernate
.LazyInitializationException
;
34 import org
.hibernate
.annotations
.Cascade
;
35 import org
.hibernate
.annotations
.CascadeType
;
36 import org
.hibernate
.annotations
.Type
;
37 import org
.hibernate
.envers
.Audited
;
38 import org
.hibernate
.search
.annotations
.Analyze
;
39 import org
.hibernate
.search
.annotations
.Field
;
41 import eu
.etaxonomy
.cdm
.model
.description
.TextData
;
42 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
43 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.TermDefaultCacheStrategy
;
45 @XmlAccessorType(XmlAccessType
.FIELD
)
46 @XmlType(name
= "TermBase", propOrder
= {
52 DefinedTermBase
.class,
57 public abstract class TermBase
extends IdentifiableEntity
<IIdentifiableEntityCacheStrategy
>{
58 private static final long serialVersionUID
= 1471561531632115822L;
59 @SuppressWarnings("unused")
60 private static final Logger logger
= Logger
.getLogger(TermBase
.class);
62 @XmlElement(name
= "URI")
63 @Field(analyze
= Analyze
.NO
)
64 @Type(type
="uriUserType")
68 * The {@link TermType type} of this term. Needs to be the same type in a {@link DefinedTermBase defined term}
69 * and in it's {@link TermVocabulary vocabulary}.
71 @XmlAttribute(name
="TermType")
72 @Column(name
="termType")
74 @Type(type
= "eu.etaxonomy.cdm.hibernate.EnumUserType",
75 parameters
= {@org.hibernate
.annotations
.Parameter(name
= "enumClass", value
= "eu.etaxonomy.cdm.model.common.TermType")}
78 private TermType termType
;
80 @XmlElementWrapper(name
= "Representations")
81 @XmlElement(name
= "Representation")
82 @OneToMany(fetch
=FetchType
.EAGER
, orphanRemoval
=true)
83 @Cascade( { CascadeType
.SAVE_UPDATE
, CascadeType
.MERGE
, CascadeType
.DELETE
})
84 // @IndexedEmbedded no need for embedding since we are using the DefinedTermBaseClassBridge
85 private Set
<Representation
> representations
= new HashSet
<Representation
>();
87 //******************* CONSTRUCTOR *************************************/
89 //for JAXB only, TODO needed?
91 protected TermBase(){}
93 protected TermBase(TermType type
){
96 throw new IllegalArgumentException("TermType must not be null");
103 protected TermBase(TermType type
, String term
, String label
, String labelAbbrev
) {
105 this.addRepresentation(new Representation(term
, label
, labelAbbrev
, Language
.DEFAULT()) );
108 private void initCacheStrategy() {
109 this.cacheStrategy
= new TermDefaultCacheStrategy
<TermBase
>();
112 //******************** GETTER /SETTER ********************************/
114 public TermType
getTermType() {
117 public void setTermType(TermType termType
) {
118 this.termType
= termType
;
122 public Set
<Representation
> getRepresentations() {
123 return this.representations
;
126 public void addRepresentation(Representation representation
) {
127 // this.representations.add(representation);
128 this.addToSetWithChangeEvent(this.representations
, representation
, "representations");
131 public void removeRepresentation(Representation representation
) {
132 // this.representations.remove(representation);
133 this.removeFromSetWithChangeEvent(this.representations
, representation
, "representations");
136 public Representation
getRepresentation(Language lang
) {
137 for (Representation repr
: representations
){
138 Language reprLanguage
= repr
.getLanguage();
139 if (reprLanguage
!= null && reprLanguage
.equals(lang
)){
147 * @see #getPreferredRepresentation(Language)
151 public Representation
getPreferredRepresentation(Language language
) {
152 Representation repr
= getRepresentation(language
);
154 repr
= getRepresentation(Language
.DEFAULT());
157 repr
= getRepresentations().isEmpty() ?
null : getRepresentations().iterator().next();
163 * Returns the Representation in the preferred language. Preferred languages
164 * are specified by the parameter languages, which receives a list of
165 * Language instances in the order of preference. If no representation in
166 * any preferred languages is found the method falls back to return the
167 * Representation in Language.DEFAULT() and if necessary further falls back
168 * to return the first element found if any.
170 * TODO think about this fall-back strategy &
171 * see also {@link TextData#getPreferredLanguageString(List)}
176 public Representation
getPreferredRepresentation(List
<Language
> languages
) {
177 Representation repr
= null;
178 if(languages
!= null){
179 for(Language language
: languages
) {
180 repr
= getRepresentation(language
);
187 repr
= getRepresentation(Language
.DEFAULT());
190 Iterator
<Representation
> it
= getRepresentations().iterator();
192 repr
= getRepresentations().iterator().next();
198 public URI
getUri() {
202 public void setUri(URI uri
) {
207 public String
getLabel() {
208 if(getLabel(Language
.DEFAULT())!=null){
209 Representation repr
= getRepresentation(Language
.DEFAULT());
210 return (repr
== null)?
null :repr
.getLabel();
212 for (Representation r
: representations
){
213 if (r
.getLabel()!= null){
217 if (representations
.size()>0){
220 return super.getUuid().toString();
225 public String
getLabel(Language lang
) {
226 Representation repr
= this.getRepresentation(lang
);
227 return (repr
== null) ?
null : repr
.getLabel();
230 public void setLabel(String label
){
231 Language lang
= Language
.DEFAULT();
232 setLabel(label
, lang
);
235 public void setLabel(String label
, Language language
){
236 if (language
!= null){
237 Representation repr
= getRepresentation(language
);
239 repr
.setLabel(label
);
240 this.titleCache
= null; //force titleCache refresh
242 repr
= Representation
.NewInstance(null, label
, null, language
);
243 this.addRepresentation(repr
);
249 public String
getDescription() {
250 return this.getDescription(Language
.DEFAULT());
253 public String
getDescription(Language lang
) {
254 Representation repr
= this.getRepresentation(lang
);
255 return (repr
== null) ?
null :repr
.getDescription();
259 public boolean equals(Object obj
) {
263 if (TermBase
.class.isAssignableFrom(obj
.getClass())){
264 TermBase dtb
= (TermBase
)obj
;
265 if (dtb
.getUuid().equals(this.getUuid())){
273 public String
toString() {
274 //TODO eliminate nasty LazyInitializationException loggings
276 return super.toString();
277 } catch (LazyInitializationException e
) {
278 return super.toString()+" "+this.getUuid();
282 //*********************** CLONE ********************************************************/
285 * Clones <i>this</i> TermBase. This is a shortcut that enables to create
286 * a new instance that differs only slightly from <i>this</i> TermBase by
287 * modifying only some of the attributes.
289 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#clone()
290 * @see java.lang.Object#clone()
293 public Object
clone()throws CloneNotSupportedException
{
295 TermBase result
= (TermBase
) super.clone();
297 result
.representations
= new HashSet
<Representation
>();
298 for (Representation rep
: this.representations
){
299 result
.representations
.add((Representation
)rep
.clone());