2 * Copyright (C) 2007 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
.media
;
13 import java
.util
.HashMap
;
14 import java
.util
.HashSet
;
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
;
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
;
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
;
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
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.
68 * @created 08-Nov-2007 13:06:34
70 @XmlAccessorType(XmlAccessType
.FIELD
)
71 @XmlType(name
= "Media", propOrder
= {
78 @XmlRootElement(name
= "Media")
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);
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
)
94 @Cascade({CascadeType
.SAVE_UPDATE
, CascadeType
.MERGE
,CascadeType
.DELETE
, CascadeType
.DELETE_ORPHAN
, CascadeType
.REFRESH
})
96 @NotEmpty(groups
= Level2
.class)
97 private Map
<Language
,LanguageString
> title
= new HashMap
<Language
,LanguageString
>();
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
;
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
)
112 @JoinTable(name
= "Media_Description")
113 @Cascade({CascadeType
.SAVE_UPDATE
, CascadeType
.MERGE
,CascadeType
.DELETE
,CascadeType
.DELETE_ORPHAN
, CascadeType
.REFRESH
})
115 private Map
<Language
,LanguageString
> description
= new HashMap
<Language
,LanguageString
>();
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
})
124 @NotEmpty(groups
= Level2
.class)
125 private Set
<MediaRepresentation
> representations
= new HashSet
<MediaRepresentation
>();
127 @XmlElement(name
= "Artist")
129 @XmlSchemaType(name
= "IDREF")
130 @ManyToOne(fetch
= FetchType
.LAZY
)
132 @Cascade(CascadeType
.SAVE_UPDATE
)
133 private AgentBase artist
;
140 public static Media
NewInstance(){
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
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){
156 Media media
= new Media();
157 media
.addRepresentation(representation
);
166 setMediaCacheStrategy();
169 private void setMediaCacheStrategy() {
170 if (getClass() == Media
.class){
171 this.cacheStrategy
= MediaDefaultCacheStrategy
.NewInstance();
177 public Set
<MediaRepresentation
> getRepresentations(){
178 if(representations
== null) {
179 this.representations
= new HashSet
<MediaRepresentation
>();
181 return this.representations
;
184 @SuppressWarnings("deprecation")
185 public void addRepresentation(MediaRepresentation representation
){
186 if (representation
!= null){
187 this.getRepresentations().add(representation
);
188 representation
.setMedia(this);
192 @SuppressWarnings("deprecation")
193 public void removeRepresentation(MediaRepresentation representation
){
194 this.getRepresentations().remove(representation
);
195 if (representation
!= null){
196 representation
.setMedia(null);
201 public AgentBase
getArtist(){
205 public void setArtist(AgentBase artist
){
206 this.artist
= artist
;
209 //************************ title / title cache *********************************
211 public LanguageString
getTitle(){
212 return getTitle(Language
.DEFAULT());
215 public LanguageString
getTitle(Language language
){
216 return title
.get(language
);
220 public Map
<Language
,LanguageString
> getAllTitles(){
222 this.title
= new HashMap
<Language
,LanguageString
>();
227 * Adds the languageString to the {@link MultilanguageText multilanguage text}
228 * used to be the title of <i>this</i> media.
230 * @param title the languageString with the title in a particular language
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
237 public void addTitle(LanguageString title
){
238 this.putTitle(title
);
240 public void putTitle(LanguageString title
){
241 this.title
.put(title
.getLanguage(), title
);
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.
249 * @param text the title in a particular language
250 * @param language the language in which the title string is formulated
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
257 public void addTitle(String title
, Language language
){
258 this.putTitle(language
, title
);
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.
265 * @param language the language in which the title string is formulated
266 * @param text the title in a particular language
269 * @see #putTitle(LanguageString)
271 public void putTitle(Language language
, String title
){
272 this.title
.put(language
, LanguageString
.NewInstance(title
, language
));
275 public void removeTitle(Language language
){
276 this.title
.remove(language
);
281 public String
getTitleCacheByLanguage(Language lang
){
282 if (cacheStrategy
!= null){
283 return ((MediaDefaultCacheStrategy
)cacheStrategy
).getTitleCacheByLanguage(this, lang
);
293 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#setTitleCache(java.lang.String)
296 public void setTitleCache(String titleCache
) {
297 putTitle(LanguageString
.NewInstance(titleCache
, Language
.DEFAULT()));
301 * @see eu.etaxonomy.cdm.model.common.IIdentifiableEntity#getTitleCache()
304 public String
getTitleCache(){
305 if (protectedTitleCache
){
306 return this.titleCache
;
308 // is title dirty, i.e. equal NULL?
309 if (titleCache
== null){
310 this.titleCache
= generateTitle();
311 this.titleCache
= getTruncatedCache(this.titleCache
) ;
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
) ;
324 public DateTime
getMediaCreated(){
325 return this.mediaCreated
;
328 public void setMediaCreated(DateTime mediaCreated
){
329 this.mediaCreated
= mediaCreated
;
332 //************* Descriptions
334 public Map
<Language
,LanguageString
> getAllDescriptions(){
335 if(this.description
== null) {
336 this.description
= new HashMap
<Language
,LanguageString
>();
338 return this.description
;
341 public LanguageString
getDescription(Language language
){
342 return getAllDescriptions().get(language
);
345 public void addDescription(LanguageString description
){
346 this.description
.put(description
.getLanguage(), description
);
349 public void addDescription(String text
, Language language
){
350 this.description
.put(language
, LanguageString
.NewInstance(text
, language
));
353 public void removeDescription(Language language
){
354 this.description
.remove(language
);
357 //************************* CLONE **************************/
361 * @see java.lang.Object#clone()
364 public Object
clone() throws CloneNotSupportedException
{
365 Media result
= (Media
)super.clone();
367 result
.description
= new HashMap
<Language
, LanguageString
>();
368 for (Language language
: this.description
.keySet()){
369 result
.description
.put(language
, this.description
.get(language
));
372 result
.title
= new HashMap
<Language
, LanguageString
>();
373 for (Language language
: this.title
.keySet()){
374 result
.title
.put(language
, this.title
.get(language
));
376 //media representations
377 result
.representations
= new HashSet
<MediaRepresentation
>();
378 for (MediaRepresentation mediaRepresentation
: this.representations
){
379 result
.representations
.add((MediaRepresentation
)mediaRepresentation
.clone());
381 //no changes to: artist
385 public int compareTo(Object o
) {