Project

General

Profile

Download (11.8 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.HashSet;
6
import java.util.List;
7
import java.util.Map;
8
import java.util.NoSuchElementException;
9
import java.util.Set;
10
import java.util.SortedMap;
11
import java.util.TreeMap;
12
import java.util.regex.Pattern;
13

    
14
import org.apache.log4j.Logger;
15

    
16
public class MediaUtils {
17

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

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

    
38
                return prefOne;
39

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

    
46
    /**
47
     * Filters the given List of Media by the supplied filter parameters <code>representationPartType</code>,
48
     * <code>mimeTypes</code>, <code>sizeTokens</code>, <code>widthOrDuration</code>, <code>height</code>, <code>size</code>.
49
     * Only best matching MediaRepresentation remains attached to the Media entities.
50
     * A Media entity may be completely omitted in the resulting list if  {@link #filterAndOrderMediaRepresentations(Set, Class, String[], Integer, Integer, Integer)}
51
     * is not returning any matching representation. This can be the case if a <code>representationPartType</code> is supplied.
52
     * <p>
53
     * In order to prevent the media entities returned by this method from being persisted accidentally the resulting list contains cloned versions of the originally
54
     * supplied media entities, which have the same UUIDs as the original ones.
55
     *
56
     * @param mediaList
57
     * @param representationPartType any subclass of {@link MediaRepresentationPart}
58
     * @param mimeTypes
59
     * @param sizeTokens
60
     * @param widthOrDuration
61
     * @param height
62
     * @param size
63
     * @return
64
     */
65
    public static Map<Media, MediaRepresentation> findPreferredMedia(List<Media> mediaList,
66
            Class<? extends MediaRepresentationPart> representationPartType, String[] mimeTypes, String[] sizeTokens,
67
            Integer widthOrDuration, Integer height, Integer size) {
68

    
69
        if(mimeTypes != null) {
70
            for(int i=0; i<mimeTypes.length; i++){
71
                mimeTypes[i] = mimeTypes[i].replace(':', '/');
72
            }
73
        }
74

    
75
        if(sizeTokens != null) {
76
            if(sizeTokens.length > 0){
77
                try {
78
                    size = Integer.valueOf(sizeTokens[0]);
79
                } catch (NumberFormatException nfe) {
80
                    /* IGNORE */
81
                }
82
            }
83
            if(sizeTokens.length > 1){
84
                try {
85
                    widthOrDuration = Integer.valueOf(sizeTokens[1]);
86
                } catch (NumberFormatException nfe) {
87
                    /* IGNORE */
88
                }
89
            }
90
            if(sizeTokens.length > 2){
91
                try {
92
                    height = Integer.valueOf(sizeTokens[2]);
93
                } catch (NumberFormatException nfe) {
94
                    /* IGNORE */
95
                }
96
            }
97
        }
98

    
99
        Map<Media, MediaRepresentation> returnMediaList = new HashMap<Media, MediaRepresentation>(mediaList.size());
100
        if(mediaList != null){
101
            for(Media media : mediaList){
102

    
103
                Set<MediaRepresentation> candidateRepresentations = new HashSet<MediaRepresentation>();
104
                candidateRepresentations.addAll(media.getRepresentations());
105

    
106
                SortedMap<Integer, MediaRepresentation> prefRepresentations
107
                    = filterAndOrderMediaRepresentations(candidateRepresentations, representationPartType, mimeTypes, size, widthOrDuration, height);
108
                try {
109
                    if(prefRepresentations.size() > 0){
110
                        // Media.representations is a set
111
                        // so it cannot retain the sorting which has been found by filterAndOrderMediaRepresentations()
112
                        // thus we take first one and remove all other representations
113
                        returnMediaList.put(media, prefRepresentations.get(prefRepresentations.firstKey()));
114
                    }
115
                } catch (NoSuchElementException nse) {
116
                    logger.debug(nse);
117
                    /* IGNORE */
118
                }
119

    
120
            }
121
        }
122
        return returnMediaList;
123
    }
124

    
125
    /**
126
     * @param media
127
     * @param mimeTypeRegexes
128
     * @param size
129
     * @param widthOrDuration
130
     * @param height
131
     * @return
132
     *
133
     * TODO move into a media utils class
134
     * TODO implement the quality filter
135

    
136
    public static SortedMap<String, MediaRepresentation> orderMediaRepresentations(Media media, String[] mimeTypeRegexes,
137
            Integer size, Integer widthOrDuration, Integer height) {
138
        SortedMap<String, MediaRepresentation> prefRepr = new TreeMap<String, MediaRepresentation>();
139
        for (String mimeTypeRegex : mimeTypeRegexes) {
140
            // getRepresentationByMimeType
141
            Pattern mimeTypePattern = Pattern.compile(mimeTypeRegex);
142
            int representationCnt = 0;
143
            for (MediaRepresentation representation : media.getRepresentations()) {
144
                int dwa = 0;
145
                if(representation.getMimeType() == null){
146
                    prefRepr.put((dwa + representationCnt++) + "_NA", representation);
147
                } else {
148
                    Matcher mather = mimeTypePattern.matcher(representation.getMimeType());
149
                    if (mather.matches()) {
150

    
151
                        /* TODO the quality filter part is being skipped
152
                         * // look for representation with the best matching parts
153
                        for (MediaRepresentationPart part : representation.getParts()) {
154
                            if (part instanceof ImageFile) {
155
                                ImageFile image = (ImageFile) part;
156
                                int dw = image.getWidth() * image.getHeight() - height * widthOrDuration;
157
                                if (dw < 0) {
158
                                    dw *= -1;
159
                                }
160
                                dwa += dw;
161
                            }
162
                            dwa = (representation.getParts().size() > 0 ? dwa / representation.getParts().size() : 0);
163
                        }
164
                        prefRepr.put((dwa + representationCnt++) + '_' + representation.getMimeType(), representation);
165

    
166
                        // preferred mime type found => end loop
167
                        break;
168
                    }
169
                }
170
            }
171
        }
172
        return prefRepr;
173
    }
174

    
175
    */
176
    /**
177
     * @param mimeTypeRegexes
178
     * @param size
179
     * @param widthOrDuration
180
     * @param height
181
     * @return
182
     *
183
     *
184
     */
185
    private static SortedMap<Integer, MediaRepresentation> filterAndOrderMediaRepresentations(Set<MediaRepresentation> mediaRepresentations,
186
            Class<? extends MediaRepresentationPart> representationPartType, String[] mimeTypeRegexes,
187
            Integer size, Integer widthOrDuration, Integer height) {
188

    
189
        SortedMap<Integer, MediaRepresentation> prefRepr = new TreeMap<Integer, MediaRepresentation>();
190

    
191

    
192
        size = (size == null ? new Integer(0) : size );
193
        widthOrDuration = (widthOrDuration == null ? new Integer(0) : widthOrDuration);
194
        height = (height == null ? new Integer(0) : height);
195
        mimeTypeRegexes = (mimeTypeRegexes == null ? new String[]{".*"} : mimeTypeRegexes);
196

    
197
        for (String mimeTypeRegex : mimeTypeRegexes) {
198
            // getRepresentationByMimeType
199
            Pattern mimeTypePattern = Pattern.compile(mimeTypeRegex);
200
            int representationCnt = 0;
201
            for (MediaRepresentation representation : mediaRepresentations) {
202

    
203
                List<MediaRepresentationPart> matchingParts = new ArrayList<MediaRepresentationPart>();
204

    
205

    
206
                // check MIME type
207
                boolean mimeTypeOK = representation.getMimeType() == null || mimeTypePattern.matcher(representation.getMimeType()).matches();
208
                logger.debug("mimeTypeOK: " + Boolean.valueOf(mimeTypeOK).toString());
209

    
210
                int dwa = 0;
211

    
212

    
213
                //first the size is used for comparison
214
                for (MediaRepresentationPart part : representation.getParts()) {
215

    
216
                    // check representationPartType
217
                    boolean representationPartTypeOK = representationPartType == null || part.getClass().isAssignableFrom(representationPartType);
218
                    logger.debug("representationPartTypeOK: " + Boolean.valueOf(representationPartTypeOK).toString());
219

    
220
                    if ( !(representationPartTypeOK && mimeTypeOK) ) {
221
                        continue;
222
                    }
223

    
224
                    logger.debug(part + " matches");
225
                    matchingParts.add(part);
226

    
227
                    if (part.getSize()!= null){
228
                        int sizeOfPart = part.getSize();
229
                        int distance = sizeOfPart - size;
230
                        if (distance < 0) {
231
                            distance*= -1;
232
                        }
233
                        dwa += distance;
234
                    }
235

    
236
                    //if height and width/duration is defined, add this information, too
237
                    if (height != 0 && widthOrDuration != 0){
238
                        int durationWidthWeight = 0;
239

    
240
                        if (part instanceof ImageFile) {
241
                            ImageFile image = (ImageFile) part;
242
                            durationWidthWeight = image.getWidth() * image.getHeight() - height * widthOrDuration;
243
                        }
244
                        else if (part instanceof MovieFile){
245
                            MovieFile movie = (MovieFile) part;
246
                            durationWidthWeight = movie.getDuration() - widthOrDuration;
247

    
248
                        }else if (part instanceof AudioFile){
249
                            AudioFile audio = (AudioFile) part;
250
                            durationWidthWeight = audio.getDuration() - widthOrDuration;
251

    
252
                        }
253
                        if (durationWidthWeight < 0) {
254
                            durationWidthWeight *= -1;
255
                        }
256
                        dwa += durationWidthWeight;
257

    
258
                    }
259
                } // loop parts
260
                logger.debug("matchingParts.size():" + matchingParts.size());
261
                if(matchingParts.size() > 0 ){
262
                    dwa = dwa / matchingParts.size();
263

    
264
                    representation.getParts().clear();
265
                    representation.getParts().addAll(matchingParts);
266

    
267
                    //keyString =(dwa + representationCnt++) + '_' + representation.getMimeType();
268

    
269
                    prefRepr.put((dwa + representationCnt++), representation);
270
                }
271
            } // loop representations
272
        } // loop mime types
273
        logger.debug(prefRepr.size() + " preferred representations found");
274
        return prefRepr;
275
    }
276
}
(9-9/13)