In order to write the first complete Page Template for the Java Mediator for SDL Tridion Templating, I needed a Java tag similar to the @@RenderComponentPresentation@@ from Dreamweaver Templating.
The logic to write such a tag is pretty simple. However, I wanted to have a versatile tag that would not only accept a Component and a Component Template, but also the possibility to specify some 'wildcards' or, more exactly, some Regular Expressions to allow the rendering of several Component Presentations based on different criterias.
The criterias I implemented are:
Attributes component and componentTemplate can in this case Strings representing TcmUri values, or actual TcmUri objects.
Note the tag above should not be placed inside a for loop -- it will display all Component Presentations that match the specified Schema.
This will of course work also with other, non Java, mediators. For example, adding a C# TBB, the Package available to it could contain items inserted by previous TBBs. This way it is no longer needed to use the ContextVariables to pass values and objects from Page Template to Component Templates.
The logic to write such a tag is pretty simple. However, I wanted to have a versatile tag that would not only accept a Component and a Component Template, but also the possibility to specify some 'wildcards' or, more exactly, some Regular Expressions to allow the rendering of several Component Presentations based on different criterias.
The criterias I implemented are:
- Component title: in the current Page, matches each Component Presentation Component title on this Regular Expression and if a match is found, the CP is displayed;
- Component Template title: same as above, but matching is done on the Component Presentation's Component Template title;
- Schema title: same as above, only matches the Schema title of the Component in the Component Presentation;
Additionally, I wanted to have the choice of sharing the Package object a Page Template would interact with, in the Component Template. Therefore, by using an 'inherit' boolean attribute on the tag, I can specify whether the Package from the Page Template would be 'inherited' into the Component Templates.
Examples
A 'Real' Page Template
The JSP TBB below iterates over each Component Presentation in the current Page in the Package and triggers its rendering:
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@taglib prefix="t" uri="http://www.mitza.net/java/mediator/tag"%>
<html>
<head>
<title>${Page.Title}</title>
</head>
<body>
<c:forEach var="cp" items="${Page.ComponentPresentationsList}">
<t:renderComponentPresentation cp="${cp}" />
</c:forEach>
</body>
</html>
Specify Component and Component Template
The code below outputs each Component Presentation in the Page:
<c:forEach var="cp" items="${Page.ComponentPresentationsList}">
<t:renderComponentPresentation component="${cp.Component}"
componentTemplate="${cp.ComponentTemplate}" />
</c:forEach>
Specify Schema
Display all Component Presentations with Component based on the Schema with TcmUri tcm:1-2-8:
<t:renderComponentPresentation schema="tcm:1-2-8" />
Combine Schema and Component Template
Combinations of attributes are possible. The more attributes are specified, the more restrictive the matching Component Presentations will become (i.e. the operator between several attributes is AND):
<t:renderComponentPresentation schema="tcm:1-2-8" componentTemplate="tcm:1-3-32" />
Inherit Page Template Package into Component Templates
Specifying attribute inherit="true" (default, false), the Package object used during the rendering of the Page Template will be re-used (inherited) into the Component Template rendering. This means that potentially, several Component Templates can share the same Package.This will of course work also with other, non Java, mediators. For example, adding a C# TBB, the Package available to it could contain items inserted by previous TBBs. This way it is no longer needed to use the ContextVariables to pass values and objects from Page Template to Component Templates.
<c:forEach var="cp" items="${Page.ComponentPresentationsList}">
<t:renderComponentPresentation cp="${cp}" inherit="true" />
</c:forEach>
Specifying with Regular Expressions
All three attributes -- component, componentTemplate and schema, allow Regular Expressions. They will be matched on their corresponding values of the Component Presentation Component title, Component Template title and Component's Schema title. The operator between the attributes is AND. The tag renders all Component Presentations matched; no need placing it inside a loop.
<t:renderComponentPresentation schema="Article" /> - displays all CPs where the Component's Schema title contains word "Article"
<t:renderComponentPresentation componentTemplate="^Summary News$" /> - displays all CPs where the Component Template's title matches exactly "Summary News"
<t:renderComponentPresentation component="^Quarterly Report.*2012" componentTemplate="tcm:1-3-32" /> - displays all CPs where the Component's title starts with "Qarterly Report" and contains the string "2012" and are using Component Template tcm:1-3-32
Code
public class RenderComponentPresentationTag extends SimpleTagSupport {
private TcmUri component;
private Pattern componentPattern;
private TcmUri componentTemplate;
private Pattern componentTemplatePattern;
private TcmUri schema;
private Pattern schemaPattern;
private boolean inherit;
private Log log = Log.getInstance();
@Override
public void doTag() throws JspException, IOException {
log.debug("RenderComponentPresentationTag.ByTcmUri:
component=%s, componentTemplate=%s", component,
componentTemplate);
if (component != null && componentTemplate != null) {
renderComponentPresentation(component, componentTemplate);
} else {
FakePageContext pageContext =
getJspContext();
Engine engine =
pageContext.getEngine();
Package _package =
pageContext.getPackage();
Item pageItem = _package.GetByName("Page");
if (pageItem == null) {
throw new MediatorException("Cannot find item Page in the Package. Are
you in Page Template context?");
}
Page page = (Page)
engine.GetObject(pageItem);
renderComponentPresentations(page);
}
}
@Override
protected FakePageContext getJspContext() {
return (FakePageContext) super.getJspContext();
}
public void setComponent(Object
component) {
if (component instanceof TcmUri) {
this.component = (TcmUri) component;
} else if (component instanceof Component) {
this.component = ((Component) component).getId();
} else {
String value =
component.toString();
if (TcmUri.IsValid(value)) {
this.component = new TcmUri(value);
} else {
componentPattern = Pattern.compile(value);
}
}
}
public void
setComponentTemplate(Object componentTemplate) {
if (componentTemplate instanceof TcmUri) {
this.componentTemplate = (TcmUri)
componentTemplate;
} else if (componentTemplate instanceof ComponentTemplate) {
this.componentTemplate = ((ComponentTemplate)
componentTemplate).getId();
} else {
String value =
componentTemplate.toString();
if (TcmUri.IsValid(value)) {
this.componentTemplate = new TcmUri(value);
} else {
componentTemplatePattern = Pattern.compile(value);
}
}
}
public void
setCp(ComponentPresentation cp) {
this.component = cp.getComponent().getId();
this.componentTemplate =
cp.getComponentTemplate().getId();
}
public void setSchema(Object
schema) {
if (schema instanceof TcmUri) {
this.schema = (TcmUri) schema;
} else if (schema instanceof Schema) {
this.schema = ((Schema) schema).getId();
} else {
String value = schema.toString();
if (TcmUri.IsValid(value)) {
this.schema = new TcmUri(value);
} else {
schemaPattern = Pattern.compile(value);
}
}
}
public void setInherit(boolean inherit) {
this.inherit = inherit;
}
private void
renderComponentPresentations(Page page) throws IOException {
for (ComponentPresentation cp : page.getComponentPresentationsList()) {
boolean isRender = true;
Component cpComponent =
cp.getComponent();
ComponentTemplate
cpComponentTemplate = cp.getComponentTemplate();
Schema cpSchema =
cpComponent.getSchema();
TcmUri cpComponentUri =
cpComponent.getId();
TcmUri cpComponentTemplateUri =
cpComponentTemplate.getId();
if (component != null) {
isRender = component.equals(cpComponentUri);
}
if (isRender && componentPattern != null) {
isRender = componentPattern.matcher(cpComponent.getTitle()).find();
}
if (isRender && componentTemplate != null) {
isRender = componentTemplate.equals(cpComponentTemplateUri);
}
if (isRender && componentTemplatePattern != null) {
isRender = componentTemplatePattern.matcher(cpComponentTemplate.getTitle()).find();
}
if (isRender && schema != null) {
isRender = schema.equals(cpSchema.getId());
}
if (isRender && schemaPattern != null) {
isRender = schemaPattern.matcher(cpSchema.getTitle()).find();
}
if (isRender) {
renderComponentPresentation(cpComponentUri,
cpComponentTemplateUri);
}
}
}
private void
renderComponentPresentation(TcmUri component, TcmUri componentTemplate) throws IOException {
log.debug(
"RenderComponentPresentationTag.renderComponentPresentation:
component=%s, componentTemplate=%s, inherit=%b",
component, componentTemplate, inherit);
String cpContent;
FakePageContext pageContext =
getJspContext();
Engine engine =
pageContext.getEngine();
JspWriter out = pageContext.getOut();
if (inherit) {
MediatorEngine mediatorEngine =
MediatorEngine.Wrap(engine);
cpContent =
mediatorEngine.RenderComponentPresentation(component, componentTemplate);
} else {
cpContent =
engine.RenderComponentPresentation(component, componentTemplate);
}
out.print(cpContent);
}
}
Comments