Project

General

Profile

Download (14.7 KB) Statistics
| Branch: | Tag: | Revision:
1
package eu.etaxonomy.cdm.model.media;
2

    
3
import java.util.ArrayList;
4
import java.util.HashMap;
5
import java.util.LinkedHashMap;
6
import java.util.LinkedHashSet;
7
import java.util.List;
8
import java.util.Map;
9
import java.util.NoSuchElementException;
10
import java.util.Set;
11
import java.util.SortedMap;
12
import java.util.TreeMap;
13
import java.util.regex.Pattern;
14

    
15
import org.apache.log4j.Logger;
16

    
17
public class MediaUtils {
18

    
19
    private static final Logger logger = Logger.getLogger(MediaUtils.class);
20

    
21
    /**
22
     * @param representationPartType TODO
23
     * @param size
24
     * @param height
25
     * @param widthOrDuration
26
     * @param mimeTypeRegexes
27
     * @return
28
     *
29
     *
30
     */
31
    public static MediaRepresentation findBestMatchingRepresentation(Media media, Class<? extends MediaRepresentationPart> representationPartType, Integer size, Integer height, Integer widthOrDuration, String[] mimeTypes){
32
        // find best matching representations of each media
33
        SortedMap<Integer, MediaRepresentation> prefRepresentations
34
        = filterAndOrderMediaRepresentations(media.getRepresentations(), null, mimeTypes, size, widthOrDuration, height);
35
        try {
36
            // take first one and remove all other representations
37
            MediaRepresentation prefOne = prefRepresentations.get(prefRepresentations.firstKey());
38

    
39
            return prefOne;
40

    
41
        } catch (NoSuchElementException nse) {
42
            /* IGNORE */
43
        }
44
        return null;
45
    }
46

    
47
    /**
48
     * Return the first {@link MediaRepresentationPart} found for the given {@link Media}
49
     * or <code>null</code> otherwise.
50
     * @param media the media which is searched for the first part
51
     * @return the first part found or <code>null</code>
52
     */
53
    public static MediaRepresentationPart getFirstMediaRepresentationPart(Media media){
54
        if(media==null){
55
            return null;
56
        }
57
        MediaRepresentationPart mediaRepresentationPart = null;
58
        Set<MediaRepresentation> representations = media.getRepresentations();
59
        if(representations!=null && representations.size()>0){
60
            MediaRepresentation mediaRepresentation = representations.iterator().next();
61
            List<MediaRepresentationPart> parts = mediaRepresentation.getParts();
62
            if(parts!=null && parts.size()>0){
63
                mediaRepresentationPart = parts.iterator().next();
64
            }
65
        }
66
        return mediaRepresentationPart;
67
    }
68

    
69
    /**
70
     * Creates one single {@link MediaRepresentationPart} for the given {@link Media}
71
     * if it does not already exists. Otherwise the first part found is returned.<br>
72
     * @param media the media for which the representation part should be created
73
     * @return the first or newly created representation part
74
     */
75
    public static MediaRepresentationPart initFirstMediaRepresentationPart(Media media, boolean isImage) {
76
        MediaRepresentationPart mediaRepresentationPart = getFirstMediaRepresentationPart(media);
77
        if(mediaRepresentationPart==null){
78
            Set<MediaRepresentation> representations = media.getRepresentations();
79
            if(representations!=null && representations.size()>0){
80
                MediaRepresentation mediaRepresentation = representations.iterator().next();
81
                if(isImage){
82
                    mediaRepresentationPart = ImageFile.NewInstance(null, null);
83
                }
84
                else{
85
                    mediaRepresentationPart = MediaRepresentationPart.NewInstance(null, null);
86
                }
87
                mediaRepresentation.addRepresentationPart(mediaRepresentationPart);
88
            }
89
            else{
90
                if(isImage){
91
                    mediaRepresentationPart = ImageFile.NewInstance(null, null);
92
                }
93
                else{
94
                    mediaRepresentationPart = MediaRepresentationPart.NewInstance(null, null);
95
                }
96

    
97
                MediaRepresentation mediaRepresentation = MediaRepresentation.NewInstance();
98
                mediaRepresentation.addRepresentationPart(mediaRepresentationPart);
99
                media.addRepresentation(mediaRepresentation);
100
            }
101
        }
102
        return mediaRepresentationPart;
103
    }
104

    
105

    
106
    /**
107
     * Filters the given List of Media by the supplied filter parameters <code>representationPartType</code>,
108
     * <code>mimeTypes</code>, <code>sizeTokens</code>, <code>widthOrDuration</code>, <code>height</code>, <code>size</code>.
109
     * Only best matching MediaRepresentation remains attached to the Media entities.
110
     * A Media entity may be completely omitted in the resulting list if  {@link #filterAndOrderMediaRepresentations(Set, Class, String[], Integer, Integer, Integer)}
111
     * is not returning any matching representation. This can be the case if a <code>representationPartType</code> is supplied.
112
     * <p>
113
     * In order to prevent the media entities returned by this method from being persisted accidentally the resulting list contains cloned versions of the originally
114
     * supplied media entities, which have the same UUIDs as the original ones.
115
     *
116
     * @param mediaList
117
     * @param representationPartType any subclass of {@link MediaRepresentationPart}
118
     * @param mimeTypes
119
     * @param sizeTokens
120
     * @param widthOrDuration
121
     * @param height
122
     * @param size
123
     * @return
124
     */
125
    public static Map<Media, MediaRepresentation> findPreferredMedia(List<Media> mediaList,
126
            Class<? extends MediaRepresentationPart> representationPartType, String[] mimeTypes, String[] sizeTokens,
127
            Integer widthOrDuration, Integer height, Integer size) {
128

    
129
        if(mimeTypes != null) {
130
            for(int i=0; i<mimeTypes.length; i++){
131
                mimeTypes[i] = mimeTypes[i].replace(':', '/');
132
            }
133
        }
134

    
135
        if(sizeTokens != null) {
136
            if(sizeTokens.length > 0){
137
                try {
138
                    size = Integer.valueOf(sizeTokens[0]);
139
                } catch (NumberFormatException nfe) {
140
                    /* IGNORE */
141
                }
142
            }
143
            if(sizeTokens.length > 1){
144
                try {
145
                    widthOrDuration = Integer.valueOf(sizeTokens[1]);
146
                } catch (NumberFormatException nfe) {
147
                    /* IGNORE */
148
                }
149
            }
150
            if(sizeTokens.length > 2){
151
                try {
152
                    height = Integer.valueOf(sizeTokens[2]);
153
                } catch (NumberFormatException nfe) {
154
                    /* IGNORE */
155
                }
156
            }
157
        }
158

    
159
        Map<Media, MediaRepresentation> returnMediaList;
160
        if(mediaList != null){
161
            returnMediaList = new LinkedHashMap<>(mediaList.size());
162
            for(Media media : mediaList){
163

    
164
                Set<MediaRepresentation> candidateRepresentations = new LinkedHashSet<>();
165
                candidateRepresentations.addAll(media.getRepresentations());
166

    
167
                SortedMap<Integer, MediaRepresentation> prefRepresentations
168
                    = filterAndOrderMediaRepresentations(candidateRepresentations, representationPartType, mimeTypes, size, widthOrDuration, height);
169
                try {
170
                    if(prefRepresentations.size() > 0){
171
                        // Media.representations is a set
172
                        // so it cannot retain the sorting which has been found by filterAndOrderMediaRepresentations()
173
                        // thus we take first one and remove all other representations
174
                        returnMediaList.put(media, prefRepresentations.get(prefRepresentations.firstKey()));
175
                    }
176
                } catch (NoSuchElementException nse) {
177
                    logger.debug(nse);
178
                    /* IGNORE */
179
                }
180

    
181
            }
182
        }
183
        else{
184
            returnMediaList = new HashMap<>();
185
        }
186
        return returnMediaList;
187
    }
188

    
189
    /**
190
     * @param media
191
     * @param mimeTypeRegexes
192
     * @param size
193
     * @param widthOrDuration
194
     * @param height
195
     * @return
196
     *
197
     * TODO move into a media utils class
198
     * TODO implement the quality filter
199

    
200
    public static SortedMap<String, MediaRepresentation> orderMediaRepresentations(Media media, String[] mimeTypeRegexes,
201
            Integer size, Integer widthOrDuration, Integer height) {
202
        SortedMap<String, MediaRepresentation> prefRepr = new TreeMap<String, MediaRepresentation>();
203
        for (String mimeTypeRegex : mimeTypeRegexes) {
204
            // getRepresentationByMimeType
205
            Pattern mimeTypePattern = Pattern.compile(mimeTypeRegex);
206
            int representationCnt = 0;
207
            for (MediaRepresentation representation : media.getRepresentations()) {
208
                int dwa = 0;
209
                if(representation.getMimeType() == null){
210
                    prefRepr.put((dwa + representationCnt++) + "_NA", representation);
211
                } else {
212
                    Matcher mather = mimeTypePattern.matcher(representation.getMimeType());
213
                    if (mather.matches()) {
214

    
215
                        /* TODO the quality filter part is being skipped
216
                         * // look for representation with the best matching parts
217
                        for (MediaRepresentationPart part : representation.getParts()) {
218
                            if (part instanceof ImageFile) {
219
                                ImageFile image = (ImageFile) part;
220
                                int dw = image.getWidth() * image.getHeight() - height * widthOrDuration;
221
                                if (dw < 0) {
222
                                    dw *= -1;
223
                                }
224
                                dwa += dw;
225
                            }
226
                            dwa = (representation.getParts().size() > 0 ? dwa / representation.getParts().size() : 0);
227
                        }
228
                        prefRepr.put((dwa + representationCnt++) + '_' + representation.getMimeType(), representation);
229

    
230
                        // preferred mime type found => end loop
231
                        break;
232
                    }
233
                }
234
            }
235
        }
236
        return prefRepr;
237
    }
238

    
239
    */
240
    /**
241
     * @param mimeTypeRegexes
242
     * @param size
243
     * @param widthOrDuration
244
     * @param height
245
     * @return
246
     *
247
     *
248
     */
249
    private static SortedMap<Integer, MediaRepresentation> filterAndOrderMediaRepresentations(
250
            Set<MediaRepresentation> mediaRepresentations,
251
            Class<? extends MediaRepresentationPart> representationPartType, String[] mimeTypeRegexes,
252
            Integer size, Integer widthOrDuration, Integer height) {
253

    
254
        SortedMap<Integer, MediaRepresentation> prefRepr = new TreeMap<>();
255

    
256

    
257
        size = (size == null ? new Integer(0) : size );
258
        widthOrDuration = (widthOrDuration == null ? new Integer(0) : widthOrDuration);
259
        height = (height == null ? new Integer(0) : height);
260
        mimeTypeRegexes = (mimeTypeRegexes == null ? new String[]{".*"} : mimeTypeRegexes);
261

    
262
        for (String mimeTypeRegex : mimeTypeRegexes) {
263
            // getRepresentationByMimeType
264
            Pattern mimeTypePattern = Pattern.compile(mimeTypeRegex);
265
            int representationCnt = 0;
266
            for (MediaRepresentation representation : mediaRepresentations) {
267

    
268
                List<MediaRepresentationPart> matchingParts = new ArrayList<>();
269

    
270

    
271
                // check MIME type
272
                boolean mimeTypeOK = representation.getMimeType() == null
273
                        || mimeTypePattern.matcher(representation.getMimeType()).matches();
274
                logger.debug("mimeTypeOK: " + Boolean.valueOf(mimeTypeOK).toString());
275

    
276
                int dwa = 0;
277

    
278

    
279
                //first the size is used for comparison
280
                for (MediaRepresentationPart part : representation.getParts()) {
281

    
282
                    // check representationPartType
283
                    boolean representationPartTypeOK = representationPartType == null
284
                            || part.getClass().isAssignableFrom(representationPartType);
285
                    logger.debug("representationPartTypeOK: " + Boolean.valueOf(representationPartTypeOK).toString());
286

    
287
                    if ( !(representationPartTypeOK && mimeTypeOK) ) {
288
                        continue;
289
                    }
290

    
291
                    logger.debug(part + " matches");
292
                    matchingParts.add(part);
293

    
294
                    if (part.getSize()!= null){
295
                        int sizeOfPart = part.getSize();
296
                        int distance = sizeOfPart - size;
297
                        if (distance < 0) {
298
                            distance*= -1;
299
                        }
300
                        dwa += distance;
301
                    }
302

    
303
                    //if height and width/duration is defined, add this information, too
304
                    if (height != 0 && widthOrDuration != 0){
305
                        int durationWidthWeight = 0;
306

    
307
                        if (part instanceof ImageFile) {
308
                            ImageFile image = (ImageFile) part;
309
                            durationWidthWeight = image.getWidth() * image.getHeight() - height * widthOrDuration;
310
                        }
311
                        else if (part instanceof MovieFile){
312
                            MovieFile movie = (MovieFile) part;
313
                            durationWidthWeight = movie.getDuration() - widthOrDuration;
314

    
315
                        }else if (part instanceof AudioFile){
316
                            AudioFile audio = (AudioFile) part;
317
                            durationWidthWeight = audio.getDuration() - widthOrDuration;
318

    
319
                        }
320
                        if (durationWidthWeight < 0) {
321
                            durationWidthWeight *= -1;
322
                        }
323
                        dwa += durationWidthWeight;
324

    
325
                    }
326
                } // loop parts
327
                logger.debug("matchingParts.size():" + matchingParts.size());
328
                if(matchingParts.size() > 0 ){
329
                    dwa = dwa / matchingParts.size();
330

    
331
                    representation.getParts().clear();
332
                    representation.getParts().addAll(matchingParts);
333

    
334
                    //keyString =(dwa + representationCnt++) + '_' + representation.getMimeType();
335

    
336
                    prefRepr.put((dwa + representationCnt++), representation);
337
                }
338
            } // loop representations
339
        } // loop mime types
340
        logger.debug(prefRepr.size() + " preferred representations found");
341
        return prefRepr;
342
    }
343
}
(9-9/13)