001/*
002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *      Nelson Silva
016 */
017
018package org.nuxeo.ecm.media.publishing;
019
020import org.apache.commons.logging.Log;
021import org.apache.commons.logging.LogFactory;
022import org.jboss.seam.ScopeType;
023import org.jboss.seam.annotations.In;
024import org.jboss.seam.annotations.Name;
025import org.jboss.seam.annotations.Scope;
026import org.jboss.seam.core.Interpolator;
027import org.jboss.seam.faces.FacesMessages;
028import org.nuxeo.ecm.core.api.CoreSession;
029import org.nuxeo.ecm.core.api.DocumentModel;
030import org.nuxeo.ecm.core.work.api.Work;
031import org.nuxeo.ecm.core.work.api.WorkManager;
032import org.nuxeo.ecm.platform.actions.Action;
033import org.nuxeo.ecm.platform.actions.ActionContext;
034import org.nuxeo.ecm.platform.ui.web.api.NavigationContext;
035import org.nuxeo.ecm.platform.ui.web.api.WebActions;
036import org.nuxeo.ecm.media.publishing.adapter.PublishableMedia;
037import org.nuxeo.ecm.media.publishing.upload.MediaPublishingUploadWork;
038import org.nuxeo.ecm.webapp.action.ActionContextProvider;
039import org.nuxeo.ecm.webapp.helpers.ResourcesAccessor;
040import org.nuxeo.runtime.api.Framework;
041
042import java.io.Serializable;
043import java.util.HashMap;
044import java.util.List;
045import java.util.Map;
046
047/**
048 * @since 7.3
049 */
050@Name("mediaPublishing")
051@Scope(ScopeType.EVENT)
052public class MediaPublishingActions implements Serializable {
053
054    private static final long serialVersionUID = 1L;
055
056    private static final String MEDIA_PUBLISHING_OPTIONS_CATEGORY = "MEDIA_PUBLISHING_OPTIONS_CATEGORY";
057
058    private static final Log log = LogFactory.getLog(MediaPublishingActions.class);
059
060    @In(create = true, required = false)
061    protected transient CoreSession documentManager;
062
063    @In(create = true, required = false)
064    protected transient FacesMessages facesMessages;
065
066    @In(create = true, required = false)
067    protected transient ActionContextProvider actionContextProvider;
068
069    @In(create = true, required = false)
070    protected transient WebActions webActions;
071
072    @In(create = true)
073    protected transient ResourcesAccessor resourcesAccessor;
074
075    @In(create = true)
076    protected transient NavigationContext navigationContext;
077
078    private static String selectedAccount;
079
080    private Map<String, Object> providersStats;
081
082    private Map<String, String> providersURL;
083
084    private Map<String, String> providersEmbedCode;
085
086    private Map<String, Boolean> publishedProviders;
087
088    Map<String, String> options;
089
090    private DocumentModel currentDoc;
091
092    public MediaPublishingActions() {
093        providersStats = new HashMap<>();
094        providersEmbedCode = new HashMap<>();
095        providersURL = new HashMap<>();
096        options = new HashMap<>();
097        publishedProviders = new HashMap<>();
098    }
099
100    public String[] getAvailableServices(DocumentModel doc) {
101        return getMediaPublishingService().getAvailableProviders(doc);
102    }
103
104    public UploadStatus getUploadStatus(DocumentModel doc, String uploadServiceName) {
105        WorkManager workManager = Framework.getLocalService(WorkManager.class);
106
107        String workId = MediaPublishingUploadWork.getIdFor(doc.getRepositoryName(), doc.getId(), uploadServiceName);
108        Work.State state = workManager.getWorkState(workId);
109
110        if (state == null) {
111            return null;
112        } else {
113            switch (state) {
114                case SCHEDULED:
115                    return new UploadStatus(UploadStatus.STATUS_UPLOAD_QUEUED, new Work.Progress(0));
116                case RUNNING:
117                    return new UploadStatus(UploadStatus.STATUS_UPLOAD_PENDING, new Work.Progress(0));
118                default:
119                    return null;
120            }
121        }
122    }
123
124    public boolean isPublished(DocumentModel doc, String provider) {
125        if (!publishedProviders.containsKey(provider)) {
126            PublishableMedia media = doc.getAdapter(PublishableMedia.class);
127            boolean isPublished = media != null && media.getId(provider) != null && media.isPublishedByProvider(provider);
128            publishedProviders.put(provider, isPublished);
129        }
130        return publishedProviders.get(provider);
131    }
132
133    public String getPublishedURL(DocumentModel doc, String provider) {
134        String url = providersURL.get(provider);
135        if (url == null) {
136            PublishableMedia media = doc.getAdapter(PublishableMedia.class);
137            url = media.getUrl(provider);
138            providersURL.put(provider, url);
139        }
140        return url;
141    }
142
143    public void publish(String provider) {
144        DocumentModel doc = navigationContext.getCurrentDocument();
145        if (selectedAccount == null || selectedAccount.length() == 0) {
146            return;
147        }
148        getMediaPublishingService().publish(doc, provider, selectedAccount, options);
149        selectedAccount = null;
150    }
151
152    public void unpublish(String provider) {
153        DocumentModel doc = navigationContext.getCurrentDocument();
154        getMediaPublishingService().unpublish(doc, provider);
155        publishedProviders.remove(provider);
156    }
157
158    public String getEmbedCode(DocumentModel doc, String provider) {
159        String embedCode = providersEmbedCode.get(provider);
160        if (embedCode == null) {
161            PublishableMedia media = doc.getAdapter(PublishableMedia.class);
162            embedCode = media.getEmbedCode(provider);
163            providersEmbedCode.put(provider, embedCode);
164        }
165        return embedCode;
166    }
167
168    public Map<String, String> getStats(DocumentModel doc, String provider) {
169        Map<String, String> stats = (Map<String, String>) providersStats.get(provider);
170        if (stats == null) {
171            PublishableMedia media = doc.getAdapter(PublishableMedia.class);
172            stats = media.getStats(provider);
173            providersStats.put(provider, stats);
174        }
175        return stats;
176    }
177
178    private MediaPublishingService getMediaPublishingService() {
179        return Framework.getService(MediaPublishingService.class);
180    }
181
182    public String getStatusMessageFor(UploadStatus status) {
183        if (status == null) {
184            return "";
185        }
186        String i18nMessageTemplate = resourcesAccessor.getMessages().get(status.getMessage());
187        if (i18nMessageTemplate == null) {
188            return "";
189        } else {
190            return Interpolator.instance().interpolate(i18nMessageTemplate,
191                    status.positionInQueue, status.queueSize, status.progress.getCurrent());
192        }
193    }
194
195    public String getSelectedAccount() {
196        return selectedAccount;
197    }
198
199    public void setSelectedAccount(String selectedAccount) {
200        this.selectedAccount = selectedAccount;
201    }
202
203    public DocumentModel getCurrentDoc() {
204        if (currentDoc == null) {
205            currentDoc = navigationContext.getCurrentDocument();
206            currentDoc.refresh();
207        }
208        return currentDoc;
209    }
210
211    /**
212     * Helper to retrieve Options widgets for a given Publishing provider
213     */
214    public List<Action> getProviderOptionsWidgets(String provider) {
215        ActionContext ctx = actionContextProvider.createActionContext();
216        ctx.putLocalVariable("provider", provider);
217        return webActions.getActionsList(MEDIA_PUBLISHING_OPTIONS_CATEGORY, ctx);
218    }
219
220    public Map<String, String> getOptions() {
221        return options;
222    }
223
224    public void setOptions(Map<String, String> options) {
225        this.options = options;
226    }
227
228    /**
229     * Data transfer object to report on the state of a video upload.
230     */
231    public class UploadStatus {
232        public static final String STATUS_UPLOAD_QUEUED = "status.video.uploadQueued";
233
234        public static final String STATUS_UPLOAD_PENDING = "status.video.uploadPending";
235
236        public final String message;
237
238        public final int positionInQueue;
239
240        public final int queueSize;
241
242        public final Work.Progress progress;
243
244        public UploadStatus(String message, Work.Progress progress) {
245            this(message, progress, 0, 0);
246        }
247
248        public UploadStatus(String message, Work.Progress progress, int positionInQueue, int queueSize) {
249            this.message = message;
250            this.progress = progress;
251            this.positionInQueue = positionInQueue;
252            this.queueSize = queueSize;
253        }
254
255        public String getMessage() {
256            return message;
257        }
258
259        public Work.Progress getProgress() {
260            return progress;
261        }
262
263        public int getPositionInQueue() {
264            return positionInQueue;
265        }
266
267        public int getQueueSize() {
268            return queueSize;
269        }
270    }
271
272    public boolean canPublish(String provider) {
273        return getMediaPublishingService().getProvider(provider).isAvailable();
274    }
275
276    public boolean isMediaAvailable(DocumentModel doc, String provider) {
277        PublishableMedia media = doc.getAdapter(PublishableMedia.class);
278        return getMediaPublishingService().getProvider(provider).isMediaAvailable(media);
279    }
280}