root/trunk/cdmlib/cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/media/Media.java

Revision 12707, 13.6 kB (checked in by a.mueller, 9 months ago)

make media cache strategy available to all media classes

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