mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
. Added cm:name based path support to the UITemplate component
- this component is generally used to render FreeMarker templates directly to the page - particularly useful for Dashlet pages - now supports an additional attribute 'templatePath' which should be set to a cm:name based path to a template for rendering - For example the simplest portable dashlet JSP page to render a template would look like this: <%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> <r:template templatePath="/Company Home/Data Dictionary/Presentation Templates/my_docs.ftl" /> - Fixes http://issues.alfresco.com/browse/AWC-1091 . Additional helper override for resolving cm:name based webdav style paths to a NodeRef . ClipboardItem interface javadoc and removal of obsolete methods from implementing classes git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@4963 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -208,6 +208,19 @@ public abstract class BaseServlet extends HttpServlet
|
||||
return resolveWebDAVPath(wc, args, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the given path elements to a NodeRef in the current repository
|
||||
*
|
||||
* @param context Faces context
|
||||
* @param args The elements of the path to lookup
|
||||
* @param decode True to decode the arg from UTF-8 format, false for no decoding
|
||||
*/
|
||||
public static NodeRef resolveWebDAVPath(FacesContext context, String[] args, boolean decode)
|
||||
{
|
||||
WebApplicationContext wc = FacesContextUtils.getRequiredWebApplicationContext(context);
|
||||
return resolveWebDAVPath(wc, args, decode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the given path elements to a NodeRef in the current repository
|
||||
*
|
||||
|
@@ -103,11 +103,6 @@ abstract class AbstractClipboardItem implements ClipboardItem
|
||||
return this.icon;
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return this.ref.getId();
|
||||
}
|
||||
|
||||
public NodeRef getNodeRef()
|
||||
{
|
||||
return this.ref;
|
||||
|
@@ -28,21 +28,51 @@ import org.alfresco.service.namespace.QName;
|
||||
*/
|
||||
public interface ClipboardItem
|
||||
{
|
||||
/**
|
||||
* @return the mode status of the clipboard item, the enum can be either Cut or Copy
|
||||
*/
|
||||
public ClipboardStatus getMode();
|
||||
|
||||
/**
|
||||
* @return display label (cm:name) of the clipboard item
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* @return QName type of the clipboard item
|
||||
*/
|
||||
public QName getType();
|
||||
|
||||
/**
|
||||
* @return the app:icon property of the clipboard item
|
||||
*/
|
||||
public String getIcon();
|
||||
|
||||
public String getId();
|
||||
|
||||
/**
|
||||
* @return the NodeRef of the clipboard item
|
||||
*/
|
||||
public NodeRef getNodeRef();
|
||||
|
||||
/**
|
||||
* @return true if the item on the clipboard supports linking (.url) as a link type
|
||||
*/
|
||||
public boolean supportsLink();
|
||||
|
||||
/**
|
||||
* @param viewId JSF View Id to check against
|
||||
*
|
||||
* @return true if the clipboard item can be pasted to the specified JSF view
|
||||
*/
|
||||
public boolean canPasteToViewId(String viewId);
|
||||
|
||||
/**
|
||||
* @param fc FacesContext
|
||||
* @param viewId JSF View Id to paste into
|
||||
* @param action Clipboard action constant (@see org.alfresco.web.ui.repo.component.shelf.UIClipboardShelfItem)
|
||||
*
|
||||
* @return true on successful paste, false otherwise
|
||||
*
|
||||
* @throws Throwable on fatal error during paste
|
||||
*/
|
||||
public boolean paste(FacesContext fc, String viewId, int action) throws Throwable;
|
||||
}
|
||||
|
@@ -127,7 +127,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
|
||||
{
|
||||
// LINK operation
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Attempting to link node ID: " + getId() + " into node ID: " + destRef.getId());
|
||||
logger.debug("Attempting to link node ID: " + getNodeRef() + " into node: " + destRef.toString());
|
||||
|
||||
// we create a special Link Object node that has a property to reference the original
|
||||
// create the node using the nodeService (can only use FileFolderService for content)
|
||||
@@ -178,7 +178,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
|
||||
{
|
||||
// COPY operation
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Attempting to copy node ID: " + getId() + " into node ID: " + destRef.getId());
|
||||
logger.debug("Attempting to copy node: " + getNodeRef() + " into node ID: " + destRef.toString());
|
||||
|
||||
if (dd.isSubClass(getType(), ContentModel.TYPE_CONTENT) ||
|
||||
dd.isSubClass(getType(), ContentModel.TYPE_FOLDER))
|
||||
@@ -218,7 +218,7 @@ public class WorkspaceClipboardItem extends AbstractClipboardItem
|
||||
{
|
||||
// MOVE operation
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Attempting to move node ID: " + getId() + " into node ID: " + destRef.getId());
|
||||
logger.debug("Attempting to move node: " + getNodeRef() + " into node ID: " + destRef.toString());
|
||||
|
||||
if (dd.isSubClass(getType(), ContentModel.TYPE_CONTENT) ||
|
||||
dd.isSubClass(getType(), ContentModel.TYPE_FOLDER))
|
||||
|
@@ -18,6 +18,7 @@ package org.alfresco.web.ui.repo.component.template;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.el.ValueBinding;
|
||||
@@ -29,6 +30,7 @@ import org.alfresco.service.cmr.repository.TemplateException;
|
||||
import org.alfresco.service.cmr.repository.TemplateImageResolver;
|
||||
import org.alfresco.service.cmr.repository.TemplateService;
|
||||
import org.alfresco.web.app.Application;
|
||||
import org.alfresco.web.app.servlet.BaseServlet;
|
||||
import org.alfresco.web.bean.repository.Repository;
|
||||
import org.alfresco.web.bean.repository.User;
|
||||
import org.alfresco.web.ui.common.Utils;
|
||||
@@ -36,21 +38,30 @@ import org.alfresco.web.ui.common.component.SelfRenderingComponent;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Component responsible for rendering the output of a FreeMarker template directly to the page.
|
||||
* <p>
|
||||
* FreeMarker templates can be specified as a NodeRef or classpath location. The template output
|
||||
* will be processed against the default model merged with any custom model reference supplied to
|
||||
* the component as a value binding attribute. The output of the template is the output of the
|
||||
* component tag.
|
||||
*
|
||||
* @author Kevin Roast
|
||||
*/
|
||||
public class UITemplate extends SelfRenderingComponent
|
||||
{
|
||||
private final static String ENGINE_DEFAULT = "freemarker";
|
||||
private final static String TEMPLATE_KEY = "_template_";
|
||||
|
||||
private static Logger logger = Logger.getLogger(UITemplate.class);
|
||||
|
||||
/** Template engine name */
|
||||
private String engine = null;
|
||||
|
||||
/** Template name/path */
|
||||
/** Template name/classpath */
|
||||
private String template = null;
|
||||
|
||||
/** Template cm:name based path */
|
||||
private String templatePath = null;
|
||||
|
||||
/** Data model reference */
|
||||
private Object model = null;
|
||||
|
||||
@@ -76,7 +87,8 @@ public class UITemplate extends SelfRenderingComponent
|
||||
super.restoreState(context, values[0]);
|
||||
this.engine = (String)values[1];
|
||||
this.template = (String)values[2];
|
||||
this.model = (Object)values[3];
|
||||
this.templatePath = (String)values[3];
|
||||
this.model = (Object)values[4];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,12 +96,8 @@ public class UITemplate extends SelfRenderingComponent
|
||||
*/
|
||||
public Object saveState(FacesContext context)
|
||||
{
|
||||
Object values[] = new Object[4];
|
||||
// standard component attributes are saved by the super class
|
||||
values[0] = super.saveState(context);
|
||||
values[1] = this.engine;
|
||||
values[2] = this.template;
|
||||
values[3] = this.model;
|
||||
Object values[] = new Object[] {
|
||||
super.saveState(context), this.engine, this.template, this.templatePath, this.model};
|
||||
return (values);
|
||||
}
|
||||
|
||||
@@ -104,8 +112,30 @@ public class UITemplate extends SelfRenderingComponent
|
||||
}
|
||||
|
||||
// get the template to process
|
||||
String template = getTemplate();
|
||||
if (template != null && template.length() != 0)
|
||||
String templateRef = getTemplate();
|
||||
if (templateRef == null || templateRef.length() == 0)
|
||||
{
|
||||
// no noderef/classpath template found - try a name based path
|
||||
String path = getTemplatePath();
|
||||
if (path != null && path.length() != 0)
|
||||
{
|
||||
// convert cm:name based path to a NodeRef
|
||||
StringTokenizer t = new StringTokenizer(path, "/");
|
||||
int tokenCount = t.countTokens();
|
||||
String[] elements = new String[tokenCount];
|
||||
for (int i=0; i<tokenCount; i++)
|
||||
{
|
||||
elements[i] = t.nextToken();
|
||||
}
|
||||
NodeRef pathRef = BaseServlet.resolveWebDAVPath(context, elements, false);
|
||||
if (pathRef != null)
|
||||
{
|
||||
templateRef = pathRef.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (templateRef != null && templateRef.length() != 0)
|
||||
{
|
||||
// get the class name of the processor to instantiate
|
||||
String engine = getEngine();
|
||||
@@ -117,14 +147,14 @@ public class UITemplate extends SelfRenderingComponent
|
||||
startTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
// get the data model to use - building default if required
|
||||
Object model = getModel();
|
||||
// get the data model to use - building default FreeMarker model as required
|
||||
Object model = getFreeMarkerModel(getModel(), templateRef);
|
||||
|
||||
// process the template against the model
|
||||
try
|
||||
{
|
||||
TemplateService templateService = Repository.getServiceRegistry(context).getTemplateService();
|
||||
templateService.processTemplate(engine, getTemplate(), model, context.getResponseWriter());
|
||||
templateService.processTemplate(engine, templateRef, model, context.getResponseWriter());
|
||||
}
|
||||
catch (TemplateException err)
|
||||
{
|
||||
@@ -139,6 +169,49 @@ public class UITemplate extends SelfRenderingComponent
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* By default we return a Map model containing root references to the Company Home Space,
|
||||
* the users Home Space and the Person Node for the current user.
|
||||
*
|
||||
* @param model Custom model to merge into default model
|
||||
* @param template Optional reference to the template to add to model
|
||||
*
|
||||
* @return Returns the data model to bind template against.
|
||||
*/
|
||||
private Object getFreeMarkerModel(Object model, String template)
|
||||
{
|
||||
if (getEngine().equals(ENGINE_DEFAULT))
|
||||
{
|
||||
// create an instance of the default FreeMarker template object model
|
||||
FacesContext fc = FacesContext.getCurrentInstance();
|
||||
ServiceRegistry services = Repository.getServiceRegistry(fc);
|
||||
User user = Application.getCurrentUser(fc);
|
||||
|
||||
// add the template itself to the model
|
||||
NodeRef templateRef = null;
|
||||
if (template.indexOf(StoreRef.URI_FILLER) != -1)
|
||||
{
|
||||
// found a noderef template
|
||||
templateRef = new NodeRef(template);
|
||||
}
|
||||
|
||||
Map root = DefaultModelHelper.buildDefaultModel(services, user, templateRef);
|
||||
|
||||
// merge models
|
||||
if (model instanceof Map)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Found valid Map model to merge with FreeMarker: " + model);
|
||||
|
||||
root.putAll((Map)model);
|
||||
}
|
||||
|
||||
model = root;
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Strongly typed component property accessors
|
||||
@@ -166,61 +239,23 @@ public class UITemplate extends SelfRenderingComponent
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the data model to bind template against.
|
||||
* <p>
|
||||
* By default we return a Map model containing root references to the Company Home Space,
|
||||
* the users Home Space and the Person Node for the current user.
|
||||
* Return the custom data model to bind template against.
|
||||
*
|
||||
* @return Returns the data model to bind template against.
|
||||
* @return Returns the custom data model to bind template against.
|
||||
*/
|
||||
public Object getModel()
|
||||
{
|
||||
if (this.model == null)
|
||||
{
|
||||
Object model = null;
|
||||
ValueBinding vb = getValueBinding("model");
|
||||
if (vb != null)
|
||||
{
|
||||
model = vb.getValue(getFacesContext());
|
||||
this.model = vb.getValue(getFacesContext());
|
||||
}
|
||||
|
||||
if (getEngine().equals(ENGINE_DEFAULT))
|
||||
{
|
||||
// create an instance of the default FreeMarker template object model
|
||||
FacesContext fc = FacesContext.getCurrentInstance();
|
||||
ServiceRegistry services = Repository.getServiceRegistry(fc);
|
||||
User user = Application.getCurrentUser(fc);
|
||||
|
||||
// add the template itself to the model
|
||||
NodeRef templateRef = null;
|
||||
if (getTemplate().indexOf(StoreRef.URI_FILLER) != -1)
|
||||
{
|
||||
// found a noderef template
|
||||
templateRef = new NodeRef(getTemplate());
|
||||
}
|
||||
|
||||
Map root = DefaultModelHelper.buildDefaultModel(services, user, templateRef);
|
||||
|
||||
// merge models
|
||||
if (model instanceof Map)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Found valid Map model to merge with FreeMarker: " + model);
|
||||
|
||||
root.putAll((Map)model);
|
||||
}
|
||||
|
||||
model = root;
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.model;
|
||||
}
|
||||
return this.model;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param model The model to set.
|
||||
*/
|
||||
@@ -230,7 +265,7 @@ public class UITemplate extends SelfRenderingComponent
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the template name.
|
||||
* @return Returns the template NodeRef/classpath.
|
||||
*/
|
||||
public String getTemplate()
|
||||
{
|
||||
@@ -249,13 +284,40 @@ public class UITemplate extends SelfRenderingComponent
|
||||
}
|
||||
|
||||
/**
|
||||
* @param template The template name to set.
|
||||
* @param template The template NodeRef/classpath to set.
|
||||
*/
|
||||
public void setTemplate(String template)
|
||||
{
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the template path.
|
||||
*/
|
||||
public String getTemplatePath()
|
||||
{
|
||||
ValueBinding vb = getValueBinding("templatePath");
|
||||
if (vb != null)
|
||||
{
|
||||
String val = (String)vb.getValue(getFacesContext());
|
||||
if (val != null)
|
||||
{
|
||||
this.templatePath = val.toString();
|
||||
}
|
||||
}
|
||||
|
||||
return this.templatePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param templatePath The template cm:name based path to set.
|
||||
*/
|
||||
public void setTemplatePath(String templatePath)
|
||||
{
|
||||
this.templatePath = templatePath;
|
||||
}
|
||||
|
||||
|
||||
/** Template Image resolver helper */
|
||||
private TemplateImageResolver imageResolver = new TemplateImageResolver()
|
||||
{
|
||||
|
@@ -52,6 +52,7 @@ public class TemplateTag extends BaseComponentTag
|
||||
|
||||
setStringProperty(component, "engine", this.engine);
|
||||
setStringProperty(component, "template", this.template);
|
||||
setStringProperty(component, "templatePath", this.templatePath);
|
||||
setStringBindingProperty(component, "model", this.model);
|
||||
}
|
||||
|
||||
@@ -64,6 +65,7 @@ public class TemplateTag extends BaseComponentTag
|
||||
|
||||
this.engine = null;
|
||||
this.template = null;
|
||||
this.templatePath = null;
|
||||
this.model = null;
|
||||
}
|
||||
|
||||
@@ -86,6 +88,16 @@ public class TemplateTag extends BaseComponentTag
|
||||
{
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the template name based path
|
||||
*
|
||||
* @param templatePath the template name based path
|
||||
*/
|
||||
public void setTemplatePath(String templatePath)
|
||||
{
|
||||
this.templatePath = templatePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the data model
|
||||
@@ -98,6 +110,9 @@ public class TemplateTag extends BaseComponentTag
|
||||
}
|
||||
|
||||
|
||||
/** the template name based path */
|
||||
private String templatePath;
|
||||
|
||||
/** the engine name */
|
||||
private String engine;
|
||||
|
||||
|
@@ -1292,7 +1292,13 @@
|
||||
|
||||
<attribute>
|
||||
<name>template</name>
|
||||
<required>true</required>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>templatePath</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
|
Reference in New Issue
Block a user