modifications in cdmlib for #2206 (modify the means to find images for the data portal)
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / media / Media.java
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.media;
11
12 import java.net.URI;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.Map;
16 import java.util.Set;
17
18 import javax.persistence.Basic;
19 import javax.persistence.Entity;
20 import javax.persistence.FetchType;
21 import javax.persistence.Inheritance;
22 import javax.persistence.InheritanceType;
23 import javax.persistence.JoinTable;
24 import javax.persistence.ManyToOne;
25 import javax.persistence.OneToMany;
26 import javax.persistence.Transient;
27 import javax.validation.constraints.NotNull;
28 import javax.xml.bind.annotation.XmlAccessType;
29 import javax.xml.bind.annotation.XmlAccessorType;
30 import javax.xml.bind.annotation.XmlElement;
31 import javax.xml.bind.annotation.XmlElementWrapper;
32 import javax.xml.bind.annotation.XmlIDREF;
33 import javax.xml.bind.annotation.XmlRootElement;
34 import javax.xml.bind.annotation.XmlSchemaType;
35 import javax.xml.bind.annotation.XmlType;
36 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
37
38 import org.apache.log4j.Logger;
39 import org.hibernate.annotations.Cascade;
40 import org.hibernate.annotations.CascadeType;
41 import org.hibernate.annotations.Type;
42 import org.hibernate.envers.Audited;
43 import org.hibernate.search.annotations.Indexed;
44 import org.hibernate.search.annotations.IndexedEmbedded;
45 import org.hibernate.validator.constraints.NotEmpty;
46 import org.joda.time.DateTime;
47
48 import eu.etaxonomy.cdm.jaxb.DateTimeAdapter;
49 import eu.etaxonomy.cdm.jaxb.MultilanguageTextAdapter;
50 import eu.etaxonomy.cdm.model.agent.AgentBase;
51 import eu.etaxonomy.cdm.model.common.IMultiLanguageTextHolder;
52 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
53 import eu.etaxonomy.cdm.model.common.Language;
54 import eu.etaxonomy.cdm.model.common.LanguageString;
55 import eu.etaxonomy.cdm.model.common.MultilanguageText;
56 import eu.etaxonomy.cdm.strategy.cache.media.MediaDefaultCacheStrategy;
57 import eu.etaxonomy.cdm.validation.Level2;
58
59 /**
60 * A {@link Media media} is any kind of media that represents a media object.
61 * This media object can have multiple {@link MediaRepresentation media representations} that differ in MIME-type
62 * and/or quality.
63 * E.g.
64 * (1) an image can have a tiff and a jpg media representation.
65 * (2) an formatted text can have a text/html or an application/pdf representation.
66 * @author m.doering
67 * @version 1.0
68 * @created 08-Nov-2007 13:06:34
69 */
70 @XmlAccessorType(XmlAccessType.FIELD)
71 @XmlType(name = "Media", propOrder = {
72 "title",
73 "mediaCreated",
74 "description",
75 "representations",
76 "artist"
77 })
78 @XmlRootElement(name = "Media")
79 @Entity
80 @Indexed
81 @Audited
82 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
83 public class Media extends IdentifiableEntity implements Cloneable, IMultiLanguageTextHolder {
84 private static final long serialVersionUID = -1927421567263473658L;
85 @SuppressWarnings("unused")
86 private static final Logger logger = Logger.getLogger(Media.class);
87
88 // TODO once hibernate annotations support custom collection type
89 // private MultilanguageText title = new MultilanguageText();
90 @XmlElement(name = "MediaTitle")
91 @XmlJavaTypeAdapter(MultilanguageTextAdapter.class)
92 @OneToMany(fetch = FetchType.LAZY)
93 @IndexedEmbedded
94 @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE,CascadeType.DELETE, CascadeType.DELETE_ORPHAN, CascadeType.REFRESH})
95 @NotNull
96 @NotEmpty(groups = Level2.class)
97 private Map<Language,LanguageString> title = new HashMap<Language,LanguageString>();
98
99 //creation date of the media (not of the record)
100 @XmlElement(name = "MediaCreated", type= String.class)
101 @XmlJavaTypeAdapter(DateTimeAdapter.class)
102 @Type(type="dateTimeUserType")
103 @Basic(fetch = FetchType.LAZY)
104 private DateTime mediaCreated;
105
106 // TODO once hibernate annotations support custom collection type
107 // private MultilanguageText description = new MultilanguageText();
108 @XmlElement(name = "MediaDescription")
109 @XmlJavaTypeAdapter(MultilanguageTextAdapter.class)
110 @OneToMany(fetch = FetchType.LAZY)
111 @IndexedEmbedded
112 @JoinTable(name = "Media_Description")
113 @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE,CascadeType.DELETE,CascadeType.DELETE_ORPHAN, CascadeType.REFRESH})
114 @NotNull
115 private Map<Language,LanguageString> description = new HashMap<Language,LanguageString>();
116
117 //A single medium such as a picture can have multiple representations in files.
118 //Common are multiple resolutions or file formats for images for example
119 @XmlElementWrapper(name = "MediaRepresentations")
120 @XmlElement(name = "MediaRepresentation")
121 @OneToMany(mappedBy="media",fetch = FetchType.LAZY)
122 @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE, CascadeType.DELETE_ORPHAN, CascadeType.REFRESH})
123 @NotNull
124 @NotEmpty(groups = Level2.class)
125 private Set<MediaRepresentation> representations = new HashSet<MediaRepresentation>();
126
127 @XmlElement(name = "Artist")
128 @XmlIDREF
129 @XmlSchemaType(name = "IDREF")
130 @ManyToOne(fetch = FetchType.LAZY)
131 @IndexedEmbedded
132 @Cascade(CascadeType.SAVE_UPDATE)
133 private AgentBase artist;
134
135
136 /**
137 * Factory method
138 * @return
139 */
140 public static Media NewInstance(){
141 return new Media();
142 }
143
144
145 /**
146 * Factory method which creates a new media, adds a reprsentation including mime type and suffix information
147 * and adds to the later a representation part for a given uri and size
148 * Returns <code>null</code> if uri is empty
149 * @return Media
150 */
151 public static Media NewInstance(URI uri, Integer size, String mimeType, String suffix){
152 MediaRepresentation representation = MediaRepresentation.NewInstance(mimeType, suffix, uri, size);
153 if (representation == null){
154 return null;
155 }
156 Media media = new Media();
157 media.addRepresentation(representation);
158 return media;
159 }
160
161 /**
162 * Constructor
163 */
164 protected Media() {
165 super();
166 setMediaCacheStrategy();
167 }
168
169 private void setMediaCacheStrategy() {
170 if (getClass() == Media.class){
171 this.cacheStrategy = MediaDefaultCacheStrategy.NewInstance();
172 }
173
174 }
175
176
177 public Set<MediaRepresentation> getRepresentations(){
178 if(representations == null) {
179 this.representations = new HashSet<MediaRepresentation>();
180 }
181 return this.representations;
182 }
183
184 @SuppressWarnings("deprecation")
185 public void addRepresentation(MediaRepresentation representation){
186 if (representation != null){
187 this.getRepresentations().add(representation);
188 representation.setMedia(this);
189 }
190 }
191
192 @SuppressWarnings("deprecation")
193 public void removeRepresentation(MediaRepresentation representation){
194 this.getRepresentations().remove(representation);
195 if (representation != null){
196 representation.setMedia(null);
197 }
198
199 }
200
201 public AgentBase getArtist(){
202 return this.artist;
203 }
204
205 public void setArtist(AgentBase artist){
206 this.artist = artist;
207 }
208
209 //************************ title / title cache *********************************
210
211 public LanguageString getTitle(){
212 return getTitle(Language.DEFAULT());
213 }
214
215 public LanguageString getTitle(Language language){
216 return title.get(language);
217 }
218
219 @Transient
220 public Map<Language,LanguageString> getAllTitles(){
221 if(title == null) {
222 this.title = new HashMap<Language,LanguageString>();
223 }
224 return this.title;
225 }
226 /**
227 * Adds the languageString to the {@link MultilanguageText multilanguage text}
228 * used to be the title of <i>this</i> media.
229 *
230 * @param title the languageString with the title in a particular language
231 * @see #getTitle()
232 * @see #putTitle(Language String)
233 * @deprecated should follow the put semantic of maps, this method will be removed in v4.0
234 * Use the {@link #putTitle(LanguageString) putTitle} method instead
235 */
236 @Deprecated
237 public void addTitle(LanguageString title){
238 this.putTitle(title);
239 }
240 public void putTitle(LanguageString title){
241 this.title.put(title.getLanguage(), title);
242 }
243
244 /**
245 * Creates a {@link LanguageString language string} based on the given text string
246 * and the given {@link Language language} and adds it to the {@link MultilanguageText multilanguage text}
247 * used to be the title of <i>this</i> media.
248 *
249 * @param text the title in a particular language
250 * @param language the language in which the title string is formulated
251 * @see #getTitle()
252 * @see #putTitle(LanguageString)
253 * @deprecated should follow the put semantic of maps, this method will be removed in v4.0
254 * Use the {@link #putTitle(Language, String) putTitle} method instead
255 */
256 @Deprecated
257 public void addTitle(String title, Language language){
258 this.putTitle(language, title);
259 }
260 /**
261 * Creates a {@link LanguageString language string} based on the given text string
262 * and the given {@link Language language} and adds it to the {@link MultilanguageText multilanguage text}
263 * used to be the title of <i>this</i> media.
264 *
265 * @param language the language in which the title string is formulated
266 * @param text the title in a particular language
267 *
268 * @see #getTitle()
269 * @see #putTitle(LanguageString)
270 */
271 public void putTitle(Language language, String title){
272 this.title.put(language, LanguageString.NewInstance(title, language));
273 }
274
275 public void removeTitle(Language language){
276 this.title.remove(language);
277 }
278
279
280 @Transient
281 public String getTitleCacheByLanguage(Language lang){
282 if (cacheStrategy != null){
283 return ((MediaDefaultCacheStrategy)cacheStrategy).getTitleCacheByLanguage(this, lang);
284 }else{
285 return null;
286 }
287
288 }
289
290
291 /*
292 * (non-Javadoc)
293 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#setTitleCache(java.lang.String)
294 */
295 @Override
296 public void setTitleCache(String titleCache) {
297 putTitle(LanguageString.NewInstance(titleCache, Language.DEFAULT()));
298 }
299
300 /* (non-Javadoc)
301 * @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#getTitleCache()
302 */
303 @Override
304 public String getTitleCache(){
305 if (protectedTitleCache){
306 return this.titleCache;
307 }
308 // is title dirty, i.e. equal NULL?
309 if (titleCache == null){
310 this.titleCache = generateTitle();
311 this.titleCache = getTruncatedCache(this.titleCache) ;
312 }else{
313 //do the same as listeners on dependend objects like representations parts
314 //are not yet installed
315 this.titleCache = generateTitle();
316 this.titleCache = getTruncatedCache(this.titleCache) ;
317 }
318 return titleCache;
319 }
320
321
322
323
324 public DateTime getMediaCreated(){
325 return this.mediaCreated;
326 }
327
328 public void setMediaCreated(DateTime mediaCreated){
329 this.mediaCreated = mediaCreated;
330 }
331
332 //************* Descriptions
333
334 public Map<Language,LanguageString> getAllDescriptions(){
335 if(this.description == null) {
336 this.description = new HashMap<Language,LanguageString>();
337 }
338 return this.description;
339 }
340
341 public LanguageString getDescription(Language language){
342 return getAllDescriptions().get(language);
343 }
344
345 public void addDescription(LanguageString description){
346 this.description.put(description.getLanguage(), description);
347 }
348
349 public void addDescription(String text, Language language){
350 this.description.put(language, LanguageString.NewInstance(text, language));
351 }
352
353 public void removeDescription(Language language){
354 this.description.remove(language);
355 }
356
357 //************************* CLONE **************************/
358
359
360 /* (non-Javadoc)
361 * @see java.lang.Object#clone()
362 */
363 @Override
364 public Object clone() throws CloneNotSupportedException{
365 Media result = (Media)super.clone();
366 //description
367 result.description = new HashMap<Language, LanguageString>();
368 for (Language language: this.description.keySet()){
369 result.description.put(language, this.description.get(language));
370 }
371 //title
372 result.title = new HashMap<Language, LanguageString>();
373 for (Language language: this.title.keySet()){
374 result.title.put(language, this.title.get(language));
375 }
376 //media representations
377 result.representations = new HashSet<MediaRepresentation>();
378 for (MediaRepresentation mediaRepresentation: this.representations){
379 result.representations.add((MediaRepresentation)mediaRepresentation.clone());
380 }
381 //no changes to: artist
382 return result;
383 }
384
385 public int compareTo(Object o) {
386 return 0;
387 }
388
389
390
391 }