001/*
002 * (C) Copyright 2006-2007 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 *     Nuxeo - initial API and implementation
018 *
019 * $Id: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $
020 */
021
022package org.nuxeo.ecm.platform.picture.web;
023
024import static org.jboss.seam.ScopeType.CONVERSATION;
025
026import java.io.IOException;
027import java.io.Serializable;
028import java.util.ArrayList;
029import java.util.Arrays;
030import java.util.HashMap;
031import java.util.Map;
032
033import org.apache.commons.logging.Log;
034import org.apache.commons.logging.LogFactory;
035import org.jboss.seam.annotations.Create;
036import org.jboss.seam.annotations.Destroy;
037import org.jboss.seam.annotations.In;
038import org.jboss.seam.annotations.Name;
039import org.jboss.seam.annotations.Observer;
040import org.jboss.seam.annotations.Scope;
041import org.jboss.seam.annotations.intercept.BypassInterceptors;
042import org.jboss.seam.annotations.remoting.WebRemote;
043import org.jboss.seam.annotations.web.RequestParameter;
044import org.nuxeo.ecm.core.api.Blob;
045import org.nuxeo.ecm.core.api.CoreSession;
046import org.nuxeo.ecm.core.api.DocumentLocation;
047import org.nuxeo.ecm.core.api.DocumentModel;
048import org.nuxeo.ecm.core.api.IdRef;
049import org.nuxeo.ecm.core.api.model.Property;
050import org.nuxeo.ecm.platform.commandline.executor.api.CommandAvailability;
051import org.nuxeo.ecm.platform.commandline.executor.api.CommandLineExecutorService;
052import org.nuxeo.ecm.platform.picture.api.adapters.PictureResourceAdapter;
053import org.nuxeo.ecm.platform.ui.web.api.NavigationContext;
054import org.nuxeo.ecm.platform.ui.web.rest.RestHelper;
055import org.nuxeo.ecm.platform.ui.web.tag.fn.DocumentModelFunctions;
056import org.nuxeo.ecm.platform.ui.web.util.ComponentUtils;
057import org.nuxeo.ecm.platform.url.api.DocumentView;
058import org.nuxeo.ecm.platform.url.codec.DocumentFileCodec;
059import org.nuxeo.ecm.platform.util.RepositoryLocation;
060import org.nuxeo.ecm.webapp.helpers.EventNames;
061import org.nuxeo.ecm.webapp.helpers.ResourcesAccessor;
062import org.nuxeo.runtime.api.Framework;
063
064/**
065 * @author <a href="mailto:ldoguin@nuxeo.com">Laurent Doguin</a>
066 */
067@Name("pictureManager")
068@Scope(CONVERSATION)
069public class PictureManagerBean implements PictureManager, Serializable {
070
071    private static final long serialVersionUID = 1L;
072
073    private static final Log log = LogFactory.getLog(PictureManagerBean.class);
074
075    protected static Boolean imageMagickAvailable;
076
077    @In(create = true, required = false)
078    protected transient CoreSession documentManager;
079
080    @RequestParameter
081    protected String fileFieldFullName;
082
083    @In(required = true, create = true)
084    protected transient NavigationContext navigationContext;
085
086    @In(create = true, required = false)
087    protected ResourcesAccessor resourcesAccessor;
088
089    protected String fileurlPicture;
090
091    protected String filename;
092
093    protected Blob fileContent;
094
095    protected Integer index;
096
097    protected String cropCoords;
098
099    protected ArrayList<Map<String, Object>> selectItems;
100
101    @Override
102    @Create
103    public void initialize() {
104        log.debug("Initializing...");
105        index = 0;
106    }
107
108    protected DocumentModel getCurrentDocument() {
109        return navigationContext.getCurrentDocument();
110    }
111
112    @Override
113    @SuppressWarnings("unchecked")
114    public String getFileurlPicture() {
115        ArrayList<Map<String, Object>> views = (ArrayList) getCurrentDocument().getProperty("picture", "views");
116        return views.get(index).get("title") + ":content";
117    }
118
119    @Override
120    public void setFileurlPicture(String fileurlPicture) {
121        this.fileurlPicture = fileurlPicture;
122    }
123
124    @SuppressWarnings({ "unchecked", "rawtypes" })
125    protected void initSelectItems() {
126        selectItems = new ArrayList<Map<String, Object>>();
127        DocumentModel doc = getCurrentDocument();
128        ArrayList<Map<String, Object>> views = (ArrayList) doc.getProperty("picture", "views");
129        for (int i = 0; i < views.size(); i++) {
130            Map<String, Object> map = new HashMap<String, Object>();
131            map.put("title", views.get(i).get("title"));
132            map.put("idx", i);
133            selectItems.add(map);
134        }
135    }
136
137    @Override
138    public ArrayList getSelectItems() {
139        if (selectItems == null) {
140            initSelectItems();
141            return selectItems;
142        } else {
143            return selectItems;
144        }
145    }
146
147    @Override
148    public void setSelectItems(ArrayList selectItems) {
149        this.selectItems = selectItems;
150    }
151
152    @Override
153    public String rotate90left() throws IOException {
154        DocumentModel doc = getCurrentDocument();
155        PictureResourceAdapter picture = doc.getAdapter(PictureResourceAdapter.class);
156        picture.doRotate(-90);
157        documentManager.saveDocument(doc);
158        documentManager.save();
159        navigationContext.setCurrentDocument(doc);
160        return null;
161    }
162
163    @Override
164    public String rotate90right() throws IOException {
165        DocumentModel doc = getCurrentDocument();
166        PictureResourceAdapter picture = doc.getAdapter(PictureResourceAdapter.class);
167        picture.doRotate(90);
168        documentManager.saveDocument(doc);
169        documentManager.save();
170        navigationContext.setCurrentDocument(doc);
171        return null;
172    }
173
174    @Override
175    public String crop() throws IOException {
176        if (cropCoords != null && !cropCoords.equals("")) {
177            DocumentModel doc = getCurrentDocument();
178            PictureResourceAdapter picture = doc.getAdapter(PictureResourceAdapter.class);
179            picture.doCrop(cropCoords);
180            documentManager.saveDocument(doc);
181            documentManager.save();
182            navigationContext.setCurrentDocument(doc);
183        }
184        return null;
185    }
186
187    @Override
188    @Observer(value = { EventNames.DOCUMENT_SELECTION_CHANGED, EventNames.DOCUMENT_CHANGED })
189    @BypassInterceptors
190    public void resetFields() {
191        filename = "";
192        fileContent = null;
193        selectItems = null;
194        index = 0;
195        cropCoords = null;
196    }
197
198    @WebRemote
199    public String remoteDownload(String patternName, String docID, String blobPropertyName, String filename)
200            {
201        IdRef docref = new IdRef(docID);
202        DocumentModel doc = documentManager.getDocument(docref);
203        return DocumentModelFunctions.fileUrl(patternName, doc, blobPropertyName, filename);
204    }
205
206    @WebRemote
207    public static String urlPopup(String url) {
208        return RestHelper.addCurrentConversationParameters(url);
209    }
210
211    @Override
212    public void download(DocumentView docView) {
213        if (docView != null) {
214            DocumentLocation docLoc = docView.getDocumentLocation();
215            // fix for NXP-1799
216            if (documentManager == null) {
217                RepositoryLocation loc = new RepositoryLocation(docLoc.getServerName());
218                navigationContext.setCurrentServerLocation(loc);
219                documentManager = navigationContext.getOrCreateDocumentManager();
220            }
221            DocumentModel doc = documentManager.getDocument(docLoc.getDocRef());
222            if (doc == null) {
223                return;
224            }
225            String path = docView.getParameter(DocumentFileCodec.FILE_PROPERTY_PATH_KEY);
226            String[] propertyPath = path.split(":");
227            String title = null;
228            String field = null;
229            Property datamodel;
230            if (propertyPath.length == 2) {
231                title = propertyPath[0];
232                field = propertyPath[1];
233                datamodel = doc.getProperty("picture:views");
234            } else if (propertyPath.length == 3) {
235                String schema = propertyPath[0];
236                title = propertyPath[1];
237                field = propertyPath[2];
238                datamodel = doc.getProperty(schema + ":" + "views");
239            } else {
240                log.debug("Invalid property path: " + Arrays.toString(propertyPath));
241                return;
242            }
243            Property view = null;
244            for (Property property : datamodel) {
245                if (property.get("title").getValue().equals(title)) {
246                    view = property;
247                }
248            }
249
250            if (view == null) {
251                for (Property property : datamodel) {
252                    if (property.get("title").getValue().equals("Thumbnail")) {
253                        view = property;
254                    }
255                }
256            }
257            if (view == null) {
258                return;
259            }
260            Blob blob = (Blob) view.getValue(field);
261            String filename = (String) view.getValue("filename");
262            // download
263            ComponentUtils.download(doc, path, blob, filename, "picture");
264        }
265    }
266
267    @Override
268    @Destroy
269    public void destroy() {
270        log.debug("Removing Seam action listener...");
271        fileurlPicture = null;
272        filename = null;
273        fileContent = null;
274        index = null;
275        selectItems = null;
276    }
277
278    @Override
279    public String getFilename() {
280        return filename;
281    }
282
283    @Override
284    public void setFilename(String filename) {
285        this.filename = filename;
286    }
287
288    @Override
289    public Blob getFileContent() {
290        return fileContent;
291    }
292
293    @Override
294    public void setFileContent(Blob fileContent) {
295        this.fileContent = fileContent;
296    }
297
298    @Override
299    public Integer getIndex() {
300        return index;
301    }
302
303    @Override
304    public void setIndex(Integer index) {
305        this.index = index;
306    }
307
308    @Override
309    public String getCropCoords() {
310        return cropCoords;
311    }
312
313    @Override
314    public void setCropCoords(String cropCoords) {
315        this.cropCoords = cropCoords;
316    }
317
318    public Boolean isImageMagickAvailable() {
319        if (imageMagickAvailable == null) {
320            CommandLineExecutorService cles = Framework.getService(CommandLineExecutorService.class);
321            CommandAvailability ca = cles.getCommandAvailability("cropAndResize");
322            imageMagickAvailable = ca.isAvailable();
323        }
324        return imageMagickAvailable;
325    }
326}