001/* 002 * (C) Copyright 2008 Nuxeo SAS (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.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 * Thierry Delprat 016 * Quentin Lamerand 017 */ 018 019package org.nuxeo.ecm.webapp.action; 020 021import static org.jboss.seam.ScopeType.CONVERSATION; 022 023import java.io.Serializable; 024import java.util.ArrayList; 025import java.util.Collections; 026import java.util.HashMap; 027import java.util.List; 028import java.util.Map; 029 030import javax.faces.context.FacesContext; 031import javax.servlet.http.HttpServletRequest; 032 033import org.apache.commons.logging.Log; 034import org.apache.commons.logging.LogFactory; 035import org.jboss.seam.annotations.In; 036import org.jboss.seam.annotations.Name; 037import org.jboss.seam.annotations.Scope; 038import org.jboss.seam.annotations.remoting.WebRemote; 039import org.jboss.seam.core.Events; 040import org.jboss.seam.web.ServletContexts; 041import org.nuxeo.ecm.core.api.Blob; 042import org.nuxeo.ecm.core.api.CoreSession; 043import org.nuxeo.ecm.core.api.DocumentModel; 044import org.nuxeo.ecm.core.api.DocumentNotFoundException; 045import org.nuxeo.ecm.core.api.DocumentRef; 046import org.nuxeo.ecm.core.api.IdRef; 047import org.nuxeo.ecm.core.api.LifeCycleConstants; 048import org.nuxeo.ecm.core.api.blobholder.BlobHolder; 049import org.nuxeo.ecm.platform.actions.Action; 050import org.nuxeo.ecm.platform.actions.ActionContext; 051import org.nuxeo.ecm.platform.ui.web.api.WebActions; 052import org.nuxeo.ecm.platform.ui.web.tag.fn.DocumentModelFunctions; 053import org.nuxeo.ecm.webapp.edit.lock.LockActions; 054import org.nuxeo.ecm.webapp.helpers.EventNames; 055 056@Name("popupHelper") 057@Scope(CONVERSATION) 058public class PopupHelper implements Serializable { 059 060 private static final long serialVersionUID = 1L; 061 062 private static final Log log = LogFactory.getLog(PopupHelper.class); 063 064 public static final String POPUP_CATEGORY = "POPUP"; 065 066 @In(required = true, create = true) 067 protected transient ActionContextProvider actionContextProvider; 068 069 @In(create = true) 070 protected transient WebActions webActions; 071 072 @In(create = true) 073 protected transient DeleteActions deleteActions; 074 075 @In(create = true, required = false) 076 protected transient CoreSession documentManager; 077 078 @In(create = true) 079 protected transient LockActions lockActions; 080 081 protected DocumentModel currentContainer; 082 083 protected DocumentModel currentParent; 084 085 protected DocumentModel currentPopupDocument; 086 087 protected List<Action> unfiltredActions; 088 089 protected void computeUnfiltredPopupActions() { 090 unfiltredActions = webActions.getAllActions(POPUP_CATEGORY); 091 // unfiltredActions = 092 // webActions.getUnfiltredActionsList(POPUP_CATEGORY); 093 } 094 095 /** 096 * Returns all popup actions: used to construct HTML menu template. 097 */ 098 public List<Action> getUnfiltredPopupActions() { 099 if (unfiltredActions == null) { 100 computeUnfiltredPopupActions(); 101 } 102 103 // post filters links to add docId 104 for (Action act : unfiltredActions) { 105 String lnk = act.getLink(); 106 if (lnk.startsWith("javascript:")) { 107 lnk = lnk.replaceFirst("javascript:", ""); 108 act.setLink(lnk); 109 } 110 } 111 return unfiltredActions; 112 } 113 114 public List<Action> getAvailablePopupActions(String popupDocId) { 115 return webActions.getActionsList(POPUP_CATEGORY, createActionContext(popupDocId)); 116 } 117 118 @WebRemote 119 public List<String> getAvailableActionId(String popupDocId) { 120 List<Action> availableActions = getAvailablePopupActions(popupDocId); 121 List<String> availableActionsIds = new ArrayList<String>(availableActions.size()); 122 for (Action act : availableActions) { 123 availableActionsIds.add(act.getId()); 124 } 125 return availableActionsIds; 126 } 127 128 @WebRemote 129 public List<String> getUnavailableActionId(String popupDocId) { 130 List<String> result = new ArrayList<String>(); 131 132 List<Action> allActions = getUnfiltredPopupActions(); 133 List<String> allActionsIds = new ArrayList<String>(allActions.size()); 134 for (Action act : allActions) { 135 allActionsIds.add(act.getId()); 136 } 137 138 List<Action> availableActions = getAvailablePopupActions(popupDocId); 139 List<String> availableActionsIds = new ArrayList<String>(availableActions.size()); 140 for (Action act : availableActions) { 141 availableActionsIds.add(act.getId()); 142 } 143 144 for (String act : allActionsIds) { 145 if (!availableActionsIds.contains(act)) { 146 result.add(act); 147 } 148 } 149 150 return result; 151 } 152 153 protected ActionContext createActionContext(String popupDocId) { 154 ActionContext ctx = actionContextProvider.createActionContext(); 155 156 DocumentModel currentDocument = ctx.getCurrentDocument(); 157 158 DocumentRef popupDocRef = new IdRef(popupDocId); 159 try { 160 DocumentModel popupDoc = documentManager.getDocument(popupDocRef); 161 ctx.setCurrentDocument(popupDoc); 162 ctx.putLocalVariable("container", currentDocument); 163 currentPopupDocument = popupDoc; 164 currentContainer = currentDocument; 165 } catch (DocumentNotFoundException e) { 166 log.error(e, e); 167 } 168 169 return ctx; 170 } 171 172 @WebRemote 173 public String getNavigationURL(String docId, String tabId) { 174 Map<String, String> params = new HashMap<String, String>(); 175 176 if (tabId != null) { 177 params.put("tabId", tabId); 178 } 179 180 DocumentModel doc = documentManager.getDocument(new IdRef(docId)); 181 182 return DocumentModelFunctions.documentUrl(null, doc, null, params, false); 183 } 184 185 @WebRemote 186 public String getNavigationURLOnContainer(String tabId) { 187 Map<String, String> params = new HashMap<String, String>(); 188 if (tabId != null) { 189 params.put("tabId", tabId); 190 } 191 192 return DocumentModelFunctions.documentUrl(null, currentContainer, null, params, false); 193 } 194 195 @WebRemote 196 public String getNavigationURLOnPopupdoc(String tabId) { 197 return getNavigationURLOnPopupdoc2(tabId, null); 198 } 199 200 protected HttpServletRequest getRequest() { 201 HttpServletRequest request = ServletContexts.instance().getRequest(); 202 if (request != null) { 203 return request; 204 } 205 FacesContext context = FacesContext.getCurrentInstance(); 206 if (context != null) { 207 return (HttpServletRequest) context.getExternalContext().getRequest(); 208 } 209 return null; 210 } 211 212 @WebRemote 213 public String getNavigationURLOnPopupdoc2(String tabId, String subTabId) { 214 Map<String, String> params = new HashMap<String, String>(); 215 if (tabId != null) { 216 params.put("tabId", tabId); 217 } 218 if (subTabId != null) { 219 params.put("subTabId", subTabId); 220 } 221 return DocumentModelFunctions.documentUrl(null, currentPopupDocument, null, params, false, getRequest()); 222 } 223 224 protected Map<String, String> getCurrentTabParameters() { 225 Map<String, String> params = new HashMap<String, String>(); 226 String tabId = webActions.getCurrentTabId(); 227 if (tabId != null) { 228 params.put("tabId", tabId); 229 } 230 String subTabId = webActions.getCurrentSubTabId(); 231 if (subTabId != null) { 232 params.put("subTabId", subTabId); 233 } 234 return params; 235 } 236 237 @WebRemote 238 public String getCurrentURL() { 239 return DocumentModelFunctions.documentUrl(null, currentContainer, null, getCurrentTabParameters(), false); 240 } 241 242 @WebRemote 243 public String getCurrentURLAfterDelete() { 244 if (!isDocumentDeleted(currentContainer)) { 245 currentParent = currentContainer; 246 } 247 return DocumentModelFunctions.documentUrl(null, currentParent, null, getCurrentTabParameters(), false); 248 } 249 250 @WebRemote 251 public String deleteDocument(String docId) { 252 DocumentModel doc = documentManager.getDocument(new IdRef(docId)); 253 currentParent = getFirstParentAfterDelete(doc); 254 List<DocumentModel> docsToDelete = new ArrayList<DocumentModel>(1); 255 docsToDelete.add(doc); 256 return deleteActions.deleteSelection(docsToDelete); 257 } 258 259 @WebRemote 260 public String editTitle(String docId, String newTitle) { 261 DocumentModel doc = documentManager.getDocument(new IdRef(docId)); 262 doc.setProperty("dublincore", "title", newTitle); 263 documentManager.saveDocument(doc); 264 documentManager.save(); 265 Events.instance().raiseEvent(EventNames.DOCUMENT_CHILDREN_CHANGED); 266 return "OK"; 267 } 268 269 public boolean getIsCurrentContainerDirectParent() { 270 if (documentManager != null && currentContainer != null && currentPopupDocument != null) { 271 DocumentModel parent = documentManager.getParentDocument(currentPopupDocument.getRef()); 272 return currentContainer.equals(parent); 273 } 274 return false; 275 } 276 277 public boolean isDocumentHasBlobAttached(DocumentModel documentModel) { 278 if (documentModel.hasSchema("file")) { 279 Blob blob = (Blob) documentModel.getProperty("file", "content"); 280 return blob != null; 281 } else { 282 return false; 283 } 284 } 285 286 public boolean isDocumentHasBlobs(DocumentModel documentModel) { 287 BlobHolder bh = documentModel.getAdapter(BlobHolder.class); 288 if (bh != null) { 289 List<Blob> docBlobs = bh.getBlobs(); 290 if (docBlobs != null && !docBlobs.isEmpty()) { 291 return true; 292 } else { 293 return false; 294 } 295 } else { 296 return false; 297 } 298 } 299 300 @WebRemote 301 public String downloadDocument(String docId, String blobPropertyName, String filenamePropertyName) 302 { 303 DocumentModel documentModel = documentManager.getDocument(new IdRef(docId)); 304 String filename = (String) documentModel.getPropertyValue(filenamePropertyName); 305 return DocumentModelFunctions.fileUrl("downloadFile", documentModel, blobPropertyName, filename); 306 } 307 308 @WebRemote 309 public String lockDocument(String docId) { 310 DocumentModel documentModel = documentManager.getDocument(new IdRef(docId)); 311 return lockActions.lockDocument(documentModel); 312 } 313 314 @WebRemote 315 public String unlockDocument(String docId) { 316 DocumentModel documentModel = documentManager.getDocument(new IdRef(docId)); 317 return lockActions.unlockDocument(documentModel); 318 } 319 320 @WebRemote 321 public String sendEmail(String docId) { 322 DocumentModel doc = documentManager.getDocument(new IdRef(docId)); 323 return DocumentModelFunctions.documentUrl(null, doc, "send_notification_email", null, false); 324 } 325 326 private DocumentModel getFirstParentAfterDelete(DocumentModel doc) { 327 List<DocumentModel> parents = documentManager.getParentDocuments(doc.getRef()); 328 parents.remove(doc); 329 Collections.reverse(parents); 330 for (DocumentModel currentParent : parents) { 331 try { 332 documentManager.getDocument(currentParent.getRef()); 333 return currentParent; 334 } catch (DocumentNotFoundException e) { 335 continue; 336 } 337 } 338 return null; 339 } 340 341 private boolean isDocumentDeleted(DocumentModel doc) { 342 // test if the document still exists in the repository 343 if (!documentManager.exists(doc.getRef())) { 344 return true; 345 } 346 // test if the document is in the trash 347 if (LifeCycleConstants.DELETED_STATE.equals(doc.getCurrentLifeCycleState())) { 348 return true; 349 } 350 return false; 351 } 352 353}