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