001/*
002 * (C) Copyright 2011 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 *     Thomas Roger
018 */
019package org.nuxeo.ecm.webapp.action;
020
021import static org.jboss.seam.ScopeType.CONVERSATION;
022import static org.nuxeo.ecm.webapp.helpers.EventNames.NAVIGATE_TO_DOCUMENT;
023
024import java.io.Serializable;
025import java.util.HashMap;
026import java.util.Map;
027
028import javax.faces.context.FacesContext;
029import javax.servlet.ServletRequest;
030import javax.servlet.http.HttpServletRequest;
031
032import org.jboss.seam.annotations.In;
033import org.jboss.seam.annotations.Install;
034import org.jboss.seam.annotations.Name;
035import org.jboss.seam.annotations.Observer;
036import org.jboss.seam.annotations.Scope;
037import org.nuxeo.ecm.core.api.CoreSession;
038import org.nuxeo.ecm.core.api.DocumentModel;
039import org.nuxeo.ecm.core.api.PathRef;
040import org.nuxeo.ecm.core.api.repository.RepositoryManager;
041import org.nuxeo.ecm.core.api.security.SecurityConstants;
042import org.nuxeo.ecm.platform.actions.Action;
043import org.nuxeo.ecm.platform.actions.ejb.ActionManager;
044import org.nuxeo.ecm.platform.types.adapter.TypeInfo;
045import org.nuxeo.ecm.platform.ui.web.api.NavigationContext;
046import org.nuxeo.ecm.platform.ui.web.api.WebActions;
047import org.nuxeo.ecm.platform.ui.web.rest.api.URLPolicyService;
048import org.nuxeo.ecm.platform.url.api.DocumentView;
049import org.nuxeo.runtime.api.Framework;
050
051/**
052 * Handle Main tab related actions.
053 * <p>
054 * Maintains a Map of tab id -> contextual document.
055 *
056 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a>
057 * @since 5.4.2
058 */
059@Name("mainTabsActions")
060@Scope(CONVERSATION)
061@Install(precedence = Install.FRAMEWORK)
062public class MainTabsActions implements Serializable {
063
064    private static final long serialVersionUID = 1L;
065
066    public static final String DEFAULT_VIEW = "view_documents";
067
068    @In(create = true)
069    protected transient RepositoryManager repositoryManager;
070
071    @In(create = true, required = false)
072    protected transient CoreSession documentManager;
073
074    @In(create = true, required = false)
075    protected transient NavigationContext navigationContext;
076
077    @In(create = true)
078    protected transient WebActions webActions;
079
080    @In(create = true, required = false)
081    protected transient ActionManager actionManager;
082
083    protected Map<String, DocumentModel> documentsByMainTabs = new HashMap<String, DocumentModel>();
084
085    @Observer({ NAVIGATE_TO_DOCUMENT })
086    public void updateContextualDocument() {
087        if (!shouldHandleRequest()) {
088            return;
089        }
090        String currentMainTab = getCurrentMainTabFromRequest();
091        if (currentMainTab == null) {
092            currentMainTab = webActions.getCurrentTabId(WebActions.MAIN_TABS_CATEGORY);
093        }
094        DocumentModel currentDocument = navigationContext.getCurrentDocument();
095        documentsByMainTabs.put(currentMainTab, currentDocument);
096    }
097
098    /**
099     * Only handle non POST requests
100     */
101    protected boolean shouldHandleRequest() {
102        ServletRequest request = (ServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
103        if (request instanceof HttpServletRequest) {
104            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
105            return !httpServletRequest.getMethod().equalsIgnoreCase("post");
106        }
107        return false;
108    }
109
110    protected String getCurrentMainTabFromRequest() {
111        URLPolicyService service = Framework.getService(URLPolicyService.class);
112        ServletRequest request = (ServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
113        if (request instanceof HttpServletRequest) {
114            DocumentView docView = service.getDocumentViewFromRequest((HttpServletRequest) request);
115            if (docView == null) {
116                return null;
117            }
118            String tabIds = docView.getParameter(WebActions.TAB_IDS_PARAMETER);
119            String mainTabId = docView.getParameter(WebActions.MAIN_TAB_ID_PARAMETER);
120            if (mainTabId != null && !mainTabId.isEmpty()) {
121                tabIds = mainTabId;
122            }
123            if (tabIds != null && tabIds.contains(WebActions.MAIN_TABS_CATEGORY)) {
124                String[] encodedActions = tabIds.split(",");
125                for (String encodedAction : encodedActions) {
126                    if (encodedAction.startsWith(WebActions.MAIN_TABS_CATEGORY)) {
127                        String[] actionInfo = encodedAction.split(":");
128                        if (actionInfo != null && actionInfo.length > 1) {
129                            return actionInfo[1];
130                        }
131                    }
132                }
133            }
134        }
135        return null;
136    }
137
138    /**
139     * Set the document used for a given {@code mainTabId}.
140     *
141     * @since 5.7
142     */
143    public void setDocumentFor(String mainTabId, DocumentModel doc) {
144        documentsByMainTabs.put(mainTabId, doc);
145    }
146
147    public DocumentModel getDocumentFor(String mainTabId) {
148        return getDocumentFor(mainTabId, navigationContext.getCurrentDocument());
149    }
150
151    public DocumentModel getDocumentFor(String mainTabId, DocumentModel defaultDocument) {
152        DocumentModel doc = documentsByMainTabs.get(mainTabId);
153        if (doc == null || !documentManager.exists(doc.getRef())
154                || !documentManager.hasPermission(doc.getRef(), SecurityConstants.READ)) {
155            documentsByMainTabs.put(mainTabId, defaultDocument);
156            doc = null;
157        }
158
159        if (doc != null && !documentManager.exists(new PathRef(doc.getPathAsString()))) {
160            // path has changed, refresh the document to have a correct URL
161            doc = documentManager.getDocument(doc.getRef());
162            documentsByMainTabs.put(mainTabId, doc);
163        }
164
165        return doc != null ? doc : defaultDocument;
166    }
167
168    public String getViewFor(Action mainTabAction) {
169        if (!mainTabAction.getId().equals(WebActions.DOCUMENTS_MAIN_TAB_ID)) {
170            return mainTabAction.getLink();
171        }
172
173        DocumentModel doc = getDocumentFor(mainTabAction.getId(), navigationContext.getCurrentDocument());
174        if (doc != null) {
175            TypeInfo typeInfo = doc.getAdapter(TypeInfo.class);
176            return typeInfo.getDefaultView();
177        }
178        return DEFAULT_VIEW;
179    }
180
181    public String getViewFor(String mainTabId) {
182        Action mainTabAction = actionManager.getAction(mainTabId);
183        return mainTabAction != null ? getViewFor(mainTabAction) : null;
184    }
185
186    public String getPatternFor(String mainTabId) {
187        URLPolicyService service = Framework.getService(URLPolicyService.class);
188        // FIXME: find some way to reference the pattern in the action,
189        // assume the pattern will be the same than the default one for
190        // now, or use the default one.
191        if (!WebActions.DOCUMENTS_MAIN_TAB_ID.equals(mainTabId) && service.hasPattern(mainTabId)) {
192            return mainTabId;
193        }
194        return service.getDefaultPatternName();
195    }
196
197    public boolean isOnMainTab(String mainTabId) {
198        if (mainTabId != null && mainTabId.equals(webActions.getCurrentTabId(WebActions.MAIN_TABS_CATEGORY))) {
199            return true;
200        }
201        return false;
202    }
203
204}