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  package org.opencastproject.publication.youtube;
23  
24  import org.opencastproject.mediapackage.Catalog;
25  import org.opencastproject.mediapackage.MediaPackage;
26  import org.opencastproject.mediapackage.MediaPackageElements;
27  import org.opencastproject.metadata.dublincore.DublinCore;
28  import org.opencastproject.metadata.dublincore.DublinCoreCatalog;
29  import org.opencastproject.metadata.dublincore.DublinCores;
30  import org.opencastproject.publication.api.PublicationException;
31  import org.opencastproject.workspace.api.Workspace;
32  
33  import org.apache.commons.io.IOUtils;
34  import org.apache.commons.lang3.StringUtils;
35  import org.slf4j.Logger;
36  import org.slf4j.LoggerFactory;
37  
38  import java.io.File;
39  import java.io.FileInputStream;
40  import java.io.InputStream;
41  
42  /**
43   * Strategy to determine destination of publication. Instances of this class are not thread-safe.
44   */
45  public class YouTubePublicationAdapter {
46  
47    /** logger instance */
48    private static final Logger logger = LoggerFactory.getLogger(YouTubePublicationAdapter.class);
49  
50    /** Media package containing publication metadata */
51    private final MediaPackage mediaPackage;
52  
53    /** Dublincore metadata catalog for the episode */
54    private final DublinCoreCatalog dcEpisode;
55  
56    /** Dublincore metadata catalog for the series */
57    private final DublinCoreCatalog dcSeries;
58  
59    /**
60     * Create a single-use strategy instance for publication to youtube
61     *
62     * @param mp
63     *          the mediapackage identifier
64     * @param workspace
65     *          the workspace service
66     * @throws PublicationException
67     */
68    public YouTubePublicationAdapter(MediaPackage mp, Workspace workspace) throws PublicationException {
69      if (mp == null) {
70        throw new PublicationException("Media package is null");
71      }
72      mediaPackage = mp;
73  
74      Catalog[] episodeCatalogs = mediaPackage.getCatalogs(MediaPackageElements.EPISODE);
75      if (episodeCatalogs.length == 0) {
76        dcEpisode = null;
77      } else {
78        dcEpisode = parseDublinCoreCatalog(episodeCatalogs[0], workspace);
79      }
80  
81      Catalog[] seriesCatalogs = mediaPackage.getCatalogs(MediaPackageElements.SERIES);
82      if (seriesCatalogs.length == 0) {
83        dcSeries = null;
84      } else {
85        dcSeries = parseDublinCoreCatalog(seriesCatalogs[0], workspace);
86      }
87    }
88  
89    /**
90     * Gets the name for a context within a publication channel.
91     *
92     * @return The playlist ID
93     */
94    public String getContextName() {
95      return mediaPackage.getSeriesTitle();
96    }
97  
98    /**
99     * Gets the name for a context within a publication channel.
100    *
101    * @return Context description
102    */
103   public String getContextDescription() {
104     return dcSeries == null ? null : dcSeries.getFirst(DublinCore.PROPERTY_DESCRIPTION);
105   }
106 
107   /**
108    * Gets the name for the episode of the media package
109    *
110    * @return the title of the episode
111    */
112   public String getEpisodeName() {
113     return dcEpisode == null ? null : dcEpisode.getFirst(DublinCore.PROPERTY_TITLE);
114   }
115 
116   /**
117    * Gets the description for the episode of the media package
118    *
119    * @return the description of the episode
120    */
121   public String getEpisodeDescription() {
122     if (dcEpisode == null) {
123       return null;
124     }
125 
126     String description = "";
127     if (dcSeries != null) {
128       description = StringUtils.trimToEmpty(dcSeries.getFirst(DublinCore.PROPERTY_TITLE));
129     }
130 
131     String episodeDescription = dcEpisode.getFirst(DublinCore.PROPERTY_DESCRIPTION);
132     if (episodeDescription != null) {
133       description += '\n' + episodeDescription;
134     }
135 
136     String episodeLicense = dcEpisode.getFirst(DublinCore.PROPERTY_LICENSE);
137     if (episodeLicense != null) {
138       description += '\n' + episodeLicense;
139     }
140 
141     return description;
142   }
143 
144   /**
145    * Parse Dublincore metadata from the workspace
146    *
147    * @param catalog
148    *          A mediapackage's catalog file
149    * @return Catalog parse from XML
150    */
151   private DublinCoreCatalog parseDublinCoreCatalog(Catalog catalog, Workspace workspace) {
152     InputStream is = null;
153     try {
154       File dcFile = workspace.get(catalog.getURI());
155       is = new FileInputStream(dcFile);
156       return DublinCores.read(is);
157     } catch (Exception e) {
158       logger.error("Error loading Dublin Core metadata: {}", e.getMessage());
159     } finally {
160       IOUtils.closeQuietly(is);
161     }
162     return null;
163   }
164 
165 }