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