Project

General

Profile

Download (13.6 KB) Statistics
| Branch: | Tag: | Revision:
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.commons.lang.StringUtils;
39
import org.apache.log4j.Logger;
40
import org.hibernate.annotations.Cascade;
41
import org.hibernate.annotations.CascadeType;
42
import org.hibernate.annotations.Type;
43
import org.hibernate.envers.Audited;
44
import org.hibernate.search.annotations.Indexed;
45
import org.hibernate.search.annotations.IndexedEmbedded;
46
import org.hibernate.validator.constraints.NotEmpty;
47
import org.joda.time.DateTime;
48

    
49
import eu.etaxonomy.cdm.jaxb.DateTimeAdapter;
50
import eu.etaxonomy.cdm.jaxb.MultilanguageTextAdapter;
51
import eu.etaxonomy.cdm.model.agent.AgentBase;
52
import eu.etaxonomy.cdm.model.common.IMultiLanguageTextHolder;
53
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
54
import eu.etaxonomy.cdm.model.common.Language;
55
import eu.etaxonomy.cdm.model.common.LanguageString;
56
import eu.etaxonomy.cdm.model.common.MultilanguageText;
57
import eu.etaxonomy.cdm.strategy.cache.media.MediaDefaultCacheStrategy;
58
import 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)
84
public 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
}
(6-6/14)