merge hibernate4 migration branch into trunk
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / common / TermBase.java
1 /**
2 * Copyright (C) 2009 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 import java.net.URI;
13 import java.util.HashSet;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.Set;
17
18 import javax.persistence.FetchType;
19 import javax.persistence.MappedSuperclass;
20 import javax.persistence.OneToMany;
21 import javax.persistence.Transient;
22 import javax.xml.bind.annotation.XmlAccessType;
23 import javax.xml.bind.annotation.XmlAccessorType;
24 import javax.xml.bind.annotation.XmlElement;
25 import javax.xml.bind.annotation.XmlElementWrapper;
26 import javax.xml.bind.annotation.XmlSeeAlso;
27 import javax.xml.bind.annotation.XmlType;
28
29 import org.apache.log4j.Logger;
30 import org.hibernate.LazyInitializationException;
31 import org.hibernate.annotations.Cascade;
32 import org.hibernate.annotations.CascadeType;
33 import org.hibernate.annotations.Type;
34 import org.hibernate.search.annotations.Analyze;
35 import org.hibernate.search.annotations.Field;
36
37 import eu.etaxonomy.cdm.model.description.FeatureTree;
38 import eu.etaxonomy.cdm.model.description.TextData;
39 import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
40 import eu.etaxonomy.cdm.strategy.cache.common.TermDefaultCacheStrategy;
41
42 @XmlAccessorType(XmlAccessType.FIELD)
43 @XmlType(name = "TermBase", propOrder = {
44 "uri",
45 "representations"
46 })
47 @XmlSeeAlso({
48 DefinedTermBase.class,
49 TermVocabulary.class,
50 FeatureTree.class
51 })
52 @MappedSuperclass
53 public abstract class TermBase extends IdentifiableEntity<IIdentifiableEntityCacheStrategy >{
54 private static final long serialVersionUID = 1471561531632115822L;
55 @SuppressWarnings("unused")
56 private static final Logger logger = Logger.getLogger(TermBase.class);
57
58 @XmlElement(name = "URI")
59 @Field(analyze = Analyze.NO)
60 @Type(type="uriUserType")
61 private URI uri;
62
63 @XmlElementWrapper(name = "Representations")
64 @XmlElement(name = "Representation")
65 @OneToMany(fetch=FetchType.EAGER, orphanRemoval=true)
66 @Cascade( { CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
67 // @IndexedEmbedded no need for embedding since we are using the DefinedTermBaseClassBridge
68 private Set<Representation> representations = new HashSet<Representation>();
69
70 public TermBase(){
71 super();
72 initCacheStrategy();
73
74 }
75 private void initCacheStrategy() {
76 this.cacheStrategy = new TermDefaultCacheStrategy<TermBase>();
77 }
78 public TermBase(String term, String label, String labelAbbrev) {
79 super();
80 initCacheStrategy();
81 this.addRepresentation(new Representation(term, label, labelAbbrev, Language.DEFAULT()) );
82 }
83
84 public Set<Representation> getRepresentations() {
85 return this.representations;
86 }
87
88 public void addRepresentation(Representation representation) {
89 this.representations.add(representation);
90 // this is just a preliminary solution (see ticket #3148)
91 if(representation.language!=null && representation.language.equals(Language.DEFAULT())){
92 this.regenerateTitleCache();
93 }
94 }
95
96 public void removeRepresentation(Representation representation) {
97 this.representations.remove(representation);
98 }
99
100 public Representation getRepresentation(Language lang) {
101 for (Representation repr : representations){
102 Language reprLanguage = repr.getLanguage();
103 if (reprLanguage != null && reprLanguage.equals(lang)){
104 return repr;
105 }
106 }
107 return null;
108 }
109
110 /**
111 * @see #getPreferredRepresentation(Language)
112 * @param language
113 * @return
114 */
115 public Representation getPreferredRepresentation(Language language) {
116 Representation repr = getRepresentation(language);
117 if(repr == null){
118 repr = getRepresentation(Language.DEFAULT());
119 }
120 if(repr == null){
121 repr = getRepresentations().iterator().next();
122 }
123 return repr;
124 }
125
126 /**
127 * Returns the Representation in the preferred language. Preferred languages
128 * are specified by the parameter languages, which receives a list of
129 * Language instances in the order of preference. If no representation in
130 * any preferred languages is found the method falls back to return the
131 * Representation in Language.DEFAULT() and if necessary further falls back
132 * to return the first element found if any.
133 *
134 * TODO think about this fall-back strategy &
135 * see also {@link TextData#getPreferredLanguageString(List)}
136 *
137 * @param languages
138 * @return
139 */
140 public Representation getPreferredRepresentation(List<Language> languages) {
141 Representation repr = null;
142 if(languages != null){
143 for(Language language : languages) {
144 repr = getRepresentation(language);
145 if(repr != null){
146 return repr;
147 }
148 }
149 }
150 if(repr == null){
151 repr = getRepresentation(Language.DEFAULT());
152 }
153 if(repr == null){
154 Iterator<Representation> it = getRepresentations().iterator();
155 if(it.hasNext()){
156 repr = getRepresentations().iterator().next();
157 }
158 }
159 return repr;
160 }
161
162 public URI getUri() {
163 return this.uri;
164 }
165
166 public void setUri(URI uri) {
167 this.uri = uri;
168 }
169
170 /* (non-Javadoc)
171 * @see eu.etaxonomy.cdm.model.common.ITerm#getLabel()
172 */
173 @Transient
174 public String getLabel() {
175 if(getLabel(Language.DEFAULT())!=null){
176 Representation repr = getRepresentation(Language.DEFAULT());
177 return (repr == null)? null :repr.getLabel();
178 }else{
179 for (Representation r : representations){
180 return r.getLabel();
181 }
182 }
183 return super.getUuid().toString();
184 }
185
186 /* (non-Javadoc)
187 * @see eu.etaxonomy.cdm.model.common.ITerm#getLabel(eu.etaxonomy.cdm.model.common.Language)
188 */
189 public String getLabel(Language lang) {
190 Representation repr = this.getRepresentation(lang);
191 return (repr == null) ? null : repr.getLabel();
192 }
193
194 public void setLabel(String label){
195 Language lang = Language.DEFAULT();
196 setLabel(label, lang);
197 }
198
199 public void setLabel(String label, Language language){
200 if (language != null){
201 Representation repr = getRepresentation(language);
202 if (repr != null){
203 repr.setLabel(label);
204 }else{
205 repr = Representation.NewInstance(null, label, null, language);
206 }
207 this.addRepresentation(repr);
208 }
209 }
210
211 /* (non-Javadoc)
212 * @see eu.etaxonomy.cdm.model.common.ITerm#getDescription()
213 */
214 @Transient
215 public String getDescription() {
216 return this.getDescription(Language.DEFAULT());
217 }
218
219 /* (non-Javadoc)
220 * @see eu.etaxonomy.cdm.model.common.ITerm#getDescription(eu.etaxonomy.cdm.model.common.Language)
221 */
222 public String getDescription(Language lang) {
223 Representation repr = this.getRepresentation(lang);
224 return (repr == null) ? null :repr.getDescription();
225 }
226
227 @Override
228 public boolean equals(Object obj) {
229 if (obj == null){
230 return false;
231 }
232 if (TermBase.class.isAssignableFrom(obj.getClass())){
233 TermBase dtb = (TermBase)obj;
234 if (dtb.getUuid().equals(this.getUuid())){
235 return true;
236 }
237 }
238 return false;
239 }
240
241 @Override
242 public String toString() {
243 //TODO eliminate nasty LazyInitializationException loggings
244 try {
245 return super.toString();
246 } catch (LazyInitializationException e) {
247 return super.toString()+" "+this.getUuid();
248 }
249 }
250
251 //*********************** CLONE ********************************************************/
252
253 /**
254 * Clones <i>this</i> TermBase. This is a shortcut that enables to create
255 * a new instance that differs only slightly from <i>this</i> TermBase by
256 * modifying only some of the attributes.
257 *
258 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#clone()
259 * @see java.lang.Object#clone()
260 */
261 @Override
262 public Object clone()throws CloneNotSupportedException {
263
264 TermBase result = (TermBase) super.clone();
265
266 result.representations = new HashSet<Representation>();
267 for (Representation rep : this.representations){
268 result.representations.add((Representation)rep.clone());
269 }
270
271
272
273 return result;
274
275 }
276
277 }