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) {
190       return null;
191     }
192     if (suffixes.containsKey("default")) {
193       return suffixes.get("default");
194     } else {
195       return suffixes.get(suffixes.values().toArray()[0]);
196     }
197   }
198 
199   /**
200    * Sets the suffix for encoded file names.
201    *
202    * @param suffix
203    *          the file suffix
204    */
205   public void setSuffix(String suffix) {
206     setSuffix("default", suffix);
207   }
208 
209   /**
210    * Sets the suffix for encoded file names.
211    *
212    * @param suffix
213    *          the file suffix
214    */
215   public void setSuffix(String tag ,String suffix) {
216     this.suffixes.put(tag, suffix);
217   }
218 
219   /**
220    * Return the mimetype as string
221    */
222   @Override
223   public String getMimeType() {
224     return mimeType;
225   }
226 
227   /**
228    * sets the mimetype of the output if applicable
229    * @param mimeType
230    * 
231    */
232   @Override
233   public void setMimeType(String mimeType) {
234     this.mimeType = mimeType;
235   }
236 
237   /**
238    * {@inheritDoc}
239    *
240    * @see org.opencastproject.composer.api.EncodingProfile#getApplicableMediaType()
241    */
242   @Override
243   public MediaType getApplicableMediaType() {
244     return applicableType;
245   }
246 
247   /**
248    * Sets the applicable type.
249    *
250    * @param applicableType
251    *          the applicableType to set
252    */
253   public void setApplicableType(MediaType applicableType) {
254     this.applicableType = applicableType;
255   }
256 
257   /**
258    * {@inheritDoc}
259    *
260    * @see org.opencastproject.composer.api.EncodingProfile#isApplicableTo(
261    *      org.opencastproject.composer.api.EncodingProfile.MediaType)
262    */
263   @Override
264   public boolean isApplicableTo(MediaType type) {
265     if (type == null) {
266       throw new IllegalArgumentException("Type must not be null");
267     }
268     return type.equals(applicableType);
269   }
270 
271   /**
272    * {@inheritDoc}
273    *
274    * @see org.opencastproject.composer.api.EncodingProfile#getExtension(java.lang.String)
275    */
276   @Override
277   public String getExtension(String key) {
278     return getExtensions().get(key);
279   }
280 
281   /**
282    * Adds the given key-value pair to the extended configuration space of this media profile.
283    *
284    * @param key
285    *          the property key
286    * @param value
287    *          the property value
288    */
289   public void addExtension(String key, String value) {
290     if (StringUtils.isBlank(key)) {
291       throw new IllegalArgumentException("Argument 'key' must not be null");
292     }
293     if (value == null) {
294       throw new IllegalArgumentException("Argument 'value' must not be null");
295     }
296     removeExtension(key);
297     extensions.add(new Extension(key, value));
298   }
299 
300   /**
301    * {@inheritDoc}
302    *
303    * @see org.opencastproject.composer.api.EncodingProfile#getExtensions()
304    */
305   @Override
306   public Map<String, String> getExtensions() {
307     Map<String, String> map = new HashMap<String, String>();
308     for (Extension extension : extensions) {
309       map.put(extension.getKey(), extension.getValue());
310     }
311     return map;
312   }
313 
314   /**
315    * Sets the extension properties for that profile. These properties may be intepreted by the encoder engine.
316    *
317    * @param extension
318    *          the extension properties
319    */
320   public void setExtensions(Map<String, String> extension) {
321     extensions.clear();
322     for (Entry<String, String> entry : extension.entrySet()) {
323       extensions.add(new Extension(entry));
324     }
325   }
326 
327   /**
328    * Removes the specified property from the extended configuation space and returns either the property value or
329    * <code>null</code> if no property was found.
330    *
331    * @param key
332    *          the property key
333    * @return the property value or <code>null</code>
334    */
335   public String removeExtension(String key) {
336     int index = -1;
337     for (int i = 0; i < extensions.size(); i++) {
338       if (extensions.get(i).getKey().equals(key)) {
339         index = i;
340         break;
341       }
342     }
343     if (index == -1) {
344       return null;
345     }
346     return extensions.remove(index).getValue();
347   }
348 
349   /**
350    * {@inheritDoc}
351    *
352    * @see org.opencastproject.composer.api.EncodingProfile#hasExtensions()
353    */
354   @Override
355   public boolean hasExtensions() {
356     return extensions != null && extensions.size() > 0;
357   }
358 
359   /**
360    * {@inheritDoc}
361    *
362    * @see org.opencastproject.composer.api.EncodingProfile#getJobLoad()
363    */
364   @Override
365   public float getJobLoad() {
366     return jobLoad;
367   }
368 
369   /**
370    * Sets the job load for this encoding profile
371    *
372    * @param jobLoad the load caused by one instance of this encoding profile running
373    */
374   public void setJobLoad(Float jobLoad) {
375     this.jobLoad = jobLoad;
376   }
377 
378   /**
379    * {@inheritDoc}
380    *
381    * @see java.lang.Object#hashCode()
382    */
383   @Override
384   public int hashCode() {
385     return identifier.hashCode();
386   }
387 
388   /**
389    * {@inheritDoc}
390    *
391    * @see java.lang.Object#equals(java.lang.Object)
392    */
393   @Override
394   public boolean equals(Object obj) {
395     if (obj instanceof EncodingProfile) {
396       EncodingProfile mf = (EncodingProfile) obj;
397       return identifier.equals(mf.getIdentifier());
398     }
399     return false;
400   }
401 
402   /**
403    * {@inheritDoc}
404    *
405    * @see java.lang.Object#toString()
406    */
407   @Override
408   public String toString() {
409     return identifier;
410   }
411 
412   @Override
413   public String getSuffix(String tag) {
414     if (suffixes.containsKey(tag)) {
415       return suffixes.get(tag);
416     } else {
417       return null;
418     }
419   }
420 
421   @Override
422   public List<String> getTags() {
423     return new ArrayList<String>(suffixes.keySet());
424   }
425 
426   /**
427    * An extension property. To read about why this class is necessary, see http://java.net/jira/browse/JAXB-223
428    */
429   @XmlAccessorType(XmlAccessType.FIELD)
430   @XmlType(name = "extension", namespace = "http://composer.opencastproject.org")
431   public static class Extension {
432 
433     /** The property key */
434     @XmlAttribute
435     private String key;
436 
437     /** The property value */
438     @XmlValue
439     private String value;
440 
441     /**
442      * No-arg constructor needed by JAXB
443      */
444     public Extension() {
445     }
446 
447     /**
448      * Constructs an extension property with a key and a value.
449      *
450      * @param key
451      *          the key
452      * @param value
453      *          the value
454      */
455     public Extension(String key, String value) {
456       this.key = key;
457       this.value = value;
458     }
459 
460     /**
461      * Constructs an extension property with a map entry.
462      *
463      * @param e
464      *          the value
465      */
466     public Extension(Map.Entry<String, String> e) {
467       key = e.getKey();
468       value = e.getValue();
469     }
470 
471     /**
472      * @return the key
473      */
474     public String getKey() {
475       return key;
476     }
477 
478     /**
479      * @return the value
480      */
481     public String getValue() {
482       return value;
483     }
484 
485     @Override
486     public boolean equals(Object obj) {
487       if (obj instanceof Extension) {
488         Extension ext = (Extension) obj;
489         return key.equals(ext.getKey()) && value.equals(ext.getValue());
490       }
491       return false;
492     }
493 
494     @Override
495     public int hashCode() {
496       return EqualsUtil.hash(key, value);
497     }
498   }
499 
500 }