View Javadoc
1   /*
2    * Licensed to The Apereo Foundation under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional
4    * information regarding copyright ownership.
5    *
6    *
7    * The Apereo Foundation licenses this file to you under the Educational
8    * Community License, Version 2.0 (the "License"); you may not use this file
9    * except in compliance with the License. You may obtain a copy of the License
10   * at:
11   *
12   *   http://opensource.org/licenses/ecl2.txt
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   *
20   */
21  
22  
23  package org.opencastproject.composer.api;
24  
25  import org.opencastproject.util.EqualsUtil;
26  
27  import org.apache.commons.lang3.StringUtils;
28  
29  import java.util.ArrayList;
30  import java.util.HashMap;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.Map.Entry;
34  
35  import javax.xml.bind.annotation.XmlAccessType;
36  import javax.xml.bind.annotation.XmlAccessorType;
37  import javax.xml.bind.annotation.XmlAttribute;
38  import javax.xml.bind.annotation.XmlElement;
39  import javax.xml.bind.annotation.XmlElementWrapper;
40  import javax.xml.bind.annotation.XmlID;
41  import javax.xml.bind.annotation.XmlRootElement;
42  import javax.xml.bind.annotation.XmlTransient;
43  import javax.xml.bind.annotation.XmlType;
44  import javax.xml.bind.annotation.XmlValue;
45  
46  /**
47   * Default implementation for encoding profiles.
48   */
49  @XmlAccessorType(XmlAccessType.FIELD)
50  @XmlType(name = "profile", namespace = "http://composer.opencastproject.org")
51  @XmlRootElement(name = "profile", namespace = "http://composer.opencastproject.org")
52  public class EncodingProfileImpl implements EncodingProfile {
53  
54    /** The profile identifier */
55    @XmlAttribute(name = "id")
56    @XmlID
57    protected String identifier = null;
58  
59    /** Format description */
60    @XmlElement(name = "name")
61    protected String name = null;
62  
63    @XmlTransient
64    protected Object source;
65  
66    /** Format type */
67    @XmlElement(name = "outputmediatype")
68    protected MediaType outputType = null;
69  
70    /** Suffix
71    @XmlElement(name = "suffix")
72    protected String suffix = null;
73    */
74  
75    /** Mime type */
76    @XmlElement(name = "mimetype")
77    protected String mimeType = null;
78  
79    /** The track type that this profile may be applied to */
80    @XmlElement(name = "inputmediatype")
81    protected MediaType applicableType = null;
82  
83    /** Installation-specific properties */
84    @XmlElement(name = "extension")
85    @XmlElementWrapper(name = "extensions")
86    protected List<Extension> extensions = new ArrayList<Extension>();
87  
88    @XmlElementWrapper(name = "suffixes")
89    protected HashMap<String,String> suffixes = new HashMap<String, String>();
90  
91    @XmlElement(name = "jobLoad")
92    protected Float jobLoad = 1.5f;
93  
94    /**
95     * Private, since the profile should be created using the static factory method.
96     *
97     * @param identifier
98     *          the profile identifier
99     * @param name
100    *          the profile name
101    */
102   public EncodingProfileImpl(String identifier, String name, Object source) {
103     this.identifier = identifier;
104     this.name = name;
105     this.source = source;
106   }
107 
108   // Needed by JAXB
109   public EncodingProfileImpl() {
110   }
111 
112   /**
113    * {@inheritDoc}
114    *
115    * @see org.opencastproject.composer.api.EncodingProfile#getIdentifier()
116    */
117   @Override
118   public String getIdentifier() {
119     return identifier;
120   }
121 
122   /**
123    * Sets the identifier
124    *
125    * @param id
126    *          the identifier
127    */
128   public void setIdentifier(String id) {
129     identifier = id;
130   }
131 
132   /**
133    * {@inheritDoc}
134    *
135    * @see org.opencastproject.composer.api.EncodingProfile#getName()
136    */
137   @Override
138   public String getName() {
139     return name;
140   }
141 
142   /**
143    * Sets the profile name
144    *
145    * @param name
146    *          the profile name
147    */
148   public void setName(String name) {
149     this.name = name;
150   }
151 
152   /**
153    * {@inheritDoc}
154    *
155    * @see org.opencastproject.composer.api.EncodingProfile#getSource()
156    */
157   @Override
158   public Object getSource() {
159     return source;
160   }
161 
162   /**
163    * {@inheritDoc}
164    *
165    * @see org.opencastproject.composer.api.EncodingProfile#getOutputType()
166    */
167   @Override
168   public MediaType getOutputType() {
169     return outputType;
170   }
171 
172   /**
173    * Sets the output type.
174    *
175    * @param type
176    *          the output type
177    */
178   public void setOutputType(MediaType type) {
179     this.outputType = type;
180   }
181 
182   /**
183    * {@inheritDoc}
184    *
185    * @see org.opencastproject.composer.api.EncodingProfile#getSuffix()
186    */
187   @Override
188   public String getSuffix() {
189     if (suffixes.keySet().size() == 0) return null;
190     if (suffixes.containsKey("default")) {
191       return suffixes.get("default");
192     } else {
193       return suffixes.get(suffixes.values().toArray()[0]);
194     }
195   }
196 
197   /**
198    * Sets the suffix for encoded file names.
199    *
200    * @param suffix
201    *          the file suffix
202    */
203   public void setSuffix(String suffix) {
204     setSuffix("default", suffix);
205   }
206 
207   /**
208    * Sets the suffix for encoded file names.
209    *
210    * @param suffix
211    *          the file suffix
212    */
213   public void setSuffix(String tag ,String suffix) {
214     this.suffixes.put(tag, suffix);
215   }
216 
217   /**
218    * Return the mimetype as string
219    */
220   @Override
221   public String getMimeType() {
222     return mimeType;
223   }
224 
225   /**
226    * sets the mimetype of the output if applicable
227    * @param mimeType
228    * 
229    */
230   @Override
231   public void setMimeType(String mimeType) {
232     this.mimeType = mimeType;
233   }
234 
235   /**
236    * {@inheritDoc}
237    *
238    * @see org.opencastproject.composer.api.EncodingProfile#getApplicableMediaType()
239    */
240   @Override
241   public MediaType getApplicableMediaType() {
242     return applicableType;
243   }
244 
245   /**
246    * Sets the applicable type.
247    *
248    * @param applicableType
249    *          the applicableType to set
250    */
251   public void setApplicableType(MediaType applicableType) {
252     this.applicableType = applicableType;
253   }
254 
255   /**
256    * {@inheritDoc}
257    *
258    * @see org.opencastproject.composer.api.EncodingProfile#isApplicableTo(org.opencastproject.composer.api.EncodingProfile.MediaType)
259    */
260   @Override
261   public boolean isApplicableTo(MediaType type) {
262     if (type == null)
263       throw new IllegalArgumentException("Type must not be null");
264     return type.equals(applicableType);
265   }
266 
267   /**
268    * {@inheritDoc}
269    *
270    * @see org.opencastproject.composer.api.EncodingProfile#getExtension(java.lang.String)
271    */
272   @Override
273   public String getExtension(String key) {
274     return getExtensions().get(key);
275   }
276 
277   /**
278    * Adds the given key-value pair to the extended configuration space of this media profile.
279    *
280    * @param key
281    *          the property key
282    * @param value
283    *          the property value
284    */
285   public void addExtension(String key, String value) {
286     if (StringUtils.isBlank(key))
287       throw new IllegalArgumentException("Argument 'key' must not be null");
288     if (value == null)
289       throw new IllegalArgumentException("Argument 'value' must not be null");
290     removeExtension(key);
291     extensions.add(new Extension(key, value));
292   }
293 
294   /**
295    * {@inheritDoc}
296    *
297    * @see org.opencastproject.composer.api.EncodingProfile#getExtensions()
298    */
299   @Override
300   public Map<String, String> getExtensions() {
301     Map<String, String> map = new HashMap<String, String>();
302     for (Extension extension : extensions) {
303       map.put(extension.getKey(), extension.getValue());
304     }
305     return map;
306   }
307 
308   /**
309    * Sets the extension properties for that profile. These properties may be intepreted by the encoder engine.
310    *
311    * @param extension
312    *          the extension properties
313    */
314   public void setExtensions(Map<String, String> extension) {
315     extensions.clear();
316     for (Entry<String, String> entry : extension.entrySet()) {
317       extensions.add(new Extension(entry));
318     }
319   }
320 
321   /**
322    * Removes the specified property from the extended configuation space and returns either the property value or
323    * <code>null</code> if no property was found.
324    *
325    * @param key
326    *          the property key
327    * @return the property value or <code>null</code>
328    */
329   public String removeExtension(String key) {
330     int index = -1;
331     for (int i = 0; i < extensions.size(); i++) {
332       if (extensions.get(i).getKey().equals(key)) {
333         index = i;
334         break;
335       }
336     }
337     if (index == -1)
338       return null;
339     return extensions.remove(index).getValue();
340   }
341 
342   /**
343    * {@inheritDoc}
344    *
345    * @see org.opencastproject.composer.api.EncodingProfile#hasExtensions()
346    */
347   @Override
348   public boolean hasExtensions() {
349     return extensions != null && extensions.size() > 0;
350   }
351 
352   /**
353    * {@inheritDoc}
354    *
355    * @see org.opencastproject.composer.api.EncodingProfile#getJobLoad()
356    */
357   @Override
358   public float getJobLoad() {
359     return jobLoad;
360   }
361 
362   /**
363    * Sets the job load for this encoding profile
364    *
365    * @param jobLoad the load caused by one instance of this encoding profile running
366    */
367   public void setJobLoad(Float jobLoad) {
368     this.jobLoad = jobLoad;
369   }
370 
371   /**
372    * {@inheritDoc}
373    *
374    * @see java.lang.Object#hashCode()
375    */
376   @Override
377   public int hashCode() {
378     return identifier.hashCode();
379   }
380 
381   /**
382    * {@inheritDoc}
383    *
384    * @see java.lang.Object#equals(java.lang.Object)
385    */
386   @Override
387   public boolean equals(Object obj) {
388     if (obj instanceof EncodingProfile) {
389       EncodingProfile mf = (EncodingProfile) obj;
390       return identifier.equals(mf.getIdentifier());
391     }
392     return false;
393   }
394 
395   /**
396    * {@inheritDoc}
397    *
398    * @see java.lang.Object#toString()
399    */
400   @Override
401   public String toString() {
402     return identifier;
403   }
404 
405   @Override
406   public String getSuffix(String tag) {
407     if (suffixes.containsKey(tag)) return suffixes.get(tag);
408     else return null;
409   }
410 
411   @Override
412   public List<String> getTags() {
413     return new ArrayList<String>(suffixes.keySet());
414   }
415 
416   /**
417    * An extension property. To read about why this class is necessary, see http://java.net/jira/browse/JAXB-223
418    */
419   @XmlAccessorType(XmlAccessType.FIELD)
420   @XmlType(name = "extension", namespace = "http://composer.opencastproject.org")
421   public static class Extension {
422 
423     /** The property key */
424     @XmlAttribute
425     private String key;
426 
427     /** The property value */
428     @XmlValue
429     private String value;
430 
431     /**
432      * No-arg constructor needed by JAXB
433      */
434     public Extension() {
435     }
436 
437     /**
438      * Constructs an extension property with a key and a value.
439      *
440      * @param key
441      *          the key
442      * @param value
443      *          the value
444      */
445     public Extension(String key, String value) {
446       this.key = key;
447       this.value = value;
448     }
449 
450     /**
451      * Constructs an extension property with a map entry.
452      *
453      * @param e
454      *          the value
455      */
456     public Extension(Map.Entry<String, String> e) {
457       key = e.getKey();
458       value = e.getValue();
459     }
460 
461     /**
462      * @return the key
463      */
464     public String getKey() {
465       return key;
466     }
467 
468     /**
469      * @return the value
470      */
471     public String getValue() {
472       return value;
473     }
474 
475     @Override
476     public boolean equals(Object obj) {
477       if (obj instanceof Extension) {
478         Extension ext = (Extension) obj;
479         return key.equals(ext.getKey()) && value.equals(ext.getValue());
480       }
481       return false;
482     }
483 
484     @Override
485     public int hashCode() {
486       return EqualsUtil.hash(key, value);
487     }
488   }
489 
490 }