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