/* * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser General Public License * (LGPL) version 2.1 which accompanies this distribution, and is available at * http://www.gnu.org/licenses/lgpl.html * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Contributors: * <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> * * $Id: RestDocumentLink.java 25089 2007-09-18 17:41:58Z ogrisel $ */ package org.nuxeo.ecm.platform.ui.web.component.document; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.Map; import javax.el.ELException; import javax.el.ValueExpression; import javax.faces.FacesException; import javax.faces.component.ContextCallback; import javax.faces.component.UIComponent; import javax.faces.component.UIParameter; import javax.faces.component.html.HtmlOutputLink; import javax.faces.context.FacesContext; import javax.faces.event.FacesEvent; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentRef; import org.nuxeo.ecm.core.api.IdRef; import org.nuxeo.ecm.platform.ui.web.api.WebActions; import org.nuxeo.ecm.platform.ui.web.component.VariableManager; import org.nuxeo.ecm.platform.ui.web.tag.fn.DocumentModelFunctions; import com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.Param; /** * Component that gives generates a Restful link given a document. * * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> */ public class RestDocumentLink extends HtmlOutputLink { public static final String COMPONENT_TYPE = RestDocumentLink.class.getName(); public static final String COMPONENT_FAMILY = RestDocumentLink.class.getName(); public static final String DEFAULT_VIEW_ID = "view_documents"; protected static final Param[] EMPTY_PARAMS = new Param[0]; protected DocumentModel document; /** * @since 5.7 */ protected String repositoryName; protected DocumentRef documentIdRef; protected String view; protected String tab; protected String subTab; /** * @since 5.4.2 */ protected String tabs; protected Boolean addTabInfo; protected String pattern; protected Boolean newConversation; /** * @since 5.7 */ protected String var; /** * @since 5.7 */ protected Boolean resolveOnly; @Override public String getFamily() { return COMPONENT_FAMILY; } /** * Override to build the URL thanks to other tag attributes information. * <p> * The document view service is queried to build it, and the tag attribute * named "value" is ignored. */ @Override public Object getValue() { DocumentModel doc = getDocument(); String repoName = getRepositoryName(); if (doc == null && repoName == null) { return null; } String viewId = getView(); Map<String, String> params = new LinkedHashMap<String, String>(); String tabValue = getTab(); String subTabValue = getSubTab(); String tabValues = getTabs(); if (tabValues == null) { tabValues = ""; } if (tabValue != null && !tabValue.isEmpty()) { if (!tabValues.isEmpty()) { tabValues += ","; } tabValues += ":" + tabValue; // params.put("tabId", tabValue); // BBB if (subTabValue != null) { tabValues += ":" + subTabValue; // params.put("subTabId", subTabValue); // BBB } } else { if (Boolean.TRUE.equals(getAddTabInfo())) { // reset tab info, resetting the tab will reset the sub tab if (!tabValues.isEmpty()) { tabValues += ","; } tabValues += ":" + WebActions.NULL_TAB_ID; // params.put("tabId", WebActions.NULL_TAB_ID); // BBB } } if (!tabValues.isEmpty()) { params.put("tabIds", tabValues); } // add parameters from f:param sub tags Param[] paramTags = getParamList(); for (Param param : paramTags) { String pn = param.name; if (pn != null && pn.length() != 0) { String pv = param.value; if (pv != null && pv.length() != 0) { params.put(pn, pv); } } } String pattern = getPattern(); return doc != null ? DocumentModelFunctions.documentUrl(pattern, doc, viewId, params, true) : DocumentModelFunctions.repositoryUrl( pattern, repoName, viewId, params, true); } protected Param[] getParamList() { if (getChildCount() > 0) { ArrayList<Param> parameterList = new ArrayList<Param>(); for (UIComponent kid : getChildren()) { if (kid instanceof UIParameter) { UIParameter uiParam = (UIParameter) kid; Object value = uiParam.getValue(); Param param = new Param(uiParam.getName(), (value == null ? null : value.toString())); parameterList.add(param); } } return parameterList.toArray(new Param[parameterList.size()]); } else { return EMPTY_PARAMS; } } // setters and getters for tag attributes public String getPattern() { if (pattern != null) { return pattern; } ValueExpression ve = getValueExpression("pattern"); if (ve != null) { try { return (String) ve.getValue(getFacesContext().getELContext()); } catch (ELException e) { throw new FacesException(e); } } else { return null; } } public void setPattern(String codec) { pattern = codec; } public DocumentModel getDocument() { if (document != null) { return document; } ValueExpression ve = getValueExpression("document"); if (ve != null) { try { return (DocumentModel) ve.getValue(getFacesContext().getELContext()); } catch (ELException e) { throw new FacesException(e); } } else { return null; } } public void setDocument(DocumentModel document) { this.document = document; } public String getRepositoryName() { if (repositoryName != null) { return repositoryName; } ValueExpression ve = getValueExpression("repositoryName"); if (ve != null) { try { return (String) ve.getValue(getFacesContext().getELContext()); } catch (ELException e) { throw new FacesException(e); } } else { return null; } } public void setRepositoryName(String repositoryName) { this.repositoryName = repositoryName; } // XXX AT: useless right now public DocumentRef getDocumentIdRef() { if (documentIdRef != null) { return documentIdRef; } ValueExpression ve = getValueExpression("documentIdRef"); if (ve != null) { try { String id = (String) ve.getValue(getFacesContext().getELContext()); if (id != null) { return new IdRef(id); } else { return null; } } catch (ELException e) { throw new FacesException(e); } } else { return null; } } public void setDocumentIdRef(DocumentRef documentIdRef) { this.documentIdRef = documentIdRef; } /** * Returns true if URL must link to a page in a new conversation. * <p> * Defaults to false. */ public Boolean getNewConversation() { if (newConversation != null) { return newConversation; } ValueExpression ve = getValueExpression("newConversation"); if (ve != null) { try { return Boolean.valueOf(!Boolean.FALSE.equals(ve.getValue(getFacesContext().getELContext()))); } catch (ELException e) { throw new FacesException(e); } } else { // default value return Boolean.FALSE; } } public void setNewConversation(Boolean newConversation) { this.newConversation = newConversation; } public String getSubTab() { if (subTab != null) { return subTab; } ValueExpression ve = getValueExpression("subTab"); if (ve != null) { try { return (String) ve.getValue(getFacesContext().getELContext()); } catch (ELException e) { throw new FacesException(e); } } else { return null; } } public void setSubTab(String subTab) { this.subTab = subTab; } public String getTab() { if (tab != null) { return tab; } ValueExpression ve = getValueExpression("tab"); if (ve != null) { try { return (String) ve.getValue(getFacesContext().getELContext()); } catch (ELException e) { throw new FacesException(e); } } else { return null; } } public void setTab(String tab) { this.tab = tab; } public String getView() { if (view != null) { return view; } ValueExpression ve = getValueExpression("view"); if (ve != null) { try { return (String) ve.getValue(getFacesContext().getELContext()); } catch (ELException e) { throw new FacesException(e); } } else { return null; } } public void setView(String view) { this.view = view; } public Boolean getAddTabInfo() { if (addTabInfo != null) { return addTabInfo; } ValueExpression ve = getValueExpression("addTabInfo"); if (ve != null) { try { return Boolean.valueOf(!Boolean.FALSE.equals(ve.getValue(getFacesContext().getELContext()))); } catch (ELException e) { throw new FacesException(e); } } else { // default value return Boolean.TRUE; } } public void setAddTabInfo(Boolean addTabInfo) { this.addTabInfo = addTabInfo; } public String getTabs() { if (tabs != null) { return tabs; } ValueExpression ve = getValueExpression("tabs"); if (ve != null) { try { return (String) ve.getValue(getFacesContext().getELContext()); } catch (ELException e) { throw new FacesException(e); } } else { return null; } } public void setTabs(String tabs) { this.tabs = tabs; } public Boolean getResolveOnly() { if (resolveOnly != null) { return resolveOnly; } ValueExpression ve = getValueExpression("resolveOnly"); if (ve != null) { try { return Boolean.valueOf(!Boolean.FALSE.equals(ve.getValue(getFacesContext().getELContext()))); } catch (ELException e) { throw new FacesException(e); } } else { // default value return Boolean.FALSE; } } public void setResolveOnly(Boolean resolveOnly) { this.resolveOnly = resolveOnly; } public String getVar() { if (var != null) { return var; } ValueExpression ve = getValueExpression("var"); if (ve != null) { try { return (String) ve.getValue(getFacesContext().getELContext()); } catch (ELException e) { throw new FacesException(e); } } else { return null; } } public void setVar(String var) { this.var = var; } // "resolveOnly" attribute management: expose value instead of rendering // the tag /** * Saves the current value exposed as param to the request, and put new * variable value instead. * <p> * Returns the original value exposed to the request. * * @since 5.7 */ protected Object beforeRender() { String var = getVar(); Object orig = VariableManager.saveRequestMapVarValue(var); if (Boolean.TRUE.equals(getResolveOnly())) { VariableManager.putVariableToRequestParam(var, getValue()); } return orig; } /** * Restored the original value exposed as param to the request, and remove * current variable value. * * @since 5.7 */ protected void afterRender(Object origVarValue) { String var = getVar(); VariableManager.restoreRequestMapVarValue(var, origVarValue); } /** * @since 5.7 */ @Override public boolean invokeOnComponent(FacesContext context, String clientId, ContextCallback callback) throws FacesException { Object varValue = beforeRender(); try { return super.invokeOnComponent(context, clientId, callback); } finally { afterRender(varValue); } } /** * @since 5.7 */ @Override public void broadcast(FacesEvent event) { Object varValue = beforeRender(); try { super.broadcast(event); } finally { afterRender(varValue); } } /** * @since 5.7 */ @Override public void encodeBegin(FacesContext context) throws IOException { if (!Boolean.TRUE.equals(getResolveOnly())) { super.encodeBegin(context); } } @Override public void encodeChildren(FacesContext context) throws IOException { Object varValue = beforeRender(); try { super.encodeChildren(context); } finally { afterRender(varValue); } } /** * @since 5.7 */ @Override public void encodeEnd(FacesContext context) throws IOException { if (!Boolean.TRUE.equals(getResolveOnly())) { super.encodeEnd(context); } } // state holder @Override public Object saveState(FacesContext context) { return new Object[] { super.saveState(context), document, documentIdRef, view, tab, subTab, tabs, addTabInfo, pattern, newConversation, var, resolveOnly }; } @Override public void restoreState(FacesContext context, Object state) { Object[] values = (Object[]) state; super.restoreState(context, values[0]); document = (DocumentModel) values[1]; documentIdRef = (DocumentRef) values[2]; view = (String) values[3]; tab = (String) values[4]; subTab = (String) values[5]; tabs = (String) values[6]; addTabInfo = (Boolean) values[7]; pattern = (String) values[8]; newConversation = (Boolean) values[9]; var = (String) values[10]; resolveOnly = (Boolean) values[11]; } }