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