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