/**
* Copyright 2005-2011 Noelios Technologies.
*
* The contents of this file are subject to the terms of one of the following
* open source licenses: LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL 1.0 (the
* "Licenses"). You can select the license that you prefer but you may not use
* this file except in compliance with one of these Licenses.
*
* You can obtain a copy of the LGPL 3.0 license at
* http://www.opensource.org/licenses/lgpl-3.0.html
*
* You can obtain a copy of the LGPL 2.1 license at
* http://www.opensource.org/licenses/lgpl-2.1.php
*
* You can obtain a copy of the CDDL 1.0 license at
* http://www.opensource.org/licenses/cddl1.php
*
* You can obtain a copy of the EPL 1.0 license at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royalty free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://www.noelios.com/products/restlet-engine
*
* Restlet is a registered trademark of Noelios Technologies.
*/
package org.restlet.ext.freemarker;
import java.io.IOException;
import java.io.Writer;
import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.data.CharacterSet;
import org.restlet.data.MediaType;
import org.restlet.ext.freemarker.internal.ResolverHashModel;
import org.restlet.representation.Representation;
import org.restlet.representation.WriterRepresentation;
import org.restlet.util.Resolver;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
/**
* FreeMarker template representation. Useful for dynamic string-based
* representations.
*
* @see <a href="http://freemarker.org/">FreeMarker home page</a>
* @author Jerome Louvel
*/
public class TemplateRepresentation extends WriterRepresentation {
/**
* Returns a FreeMarker template from a representation and a configuration.
*
* @param config
* The FreeMarker configuration.
* @param templateRepresentation
* The template representation.
* @return The template or null if not found.
*/
public static Template getTemplate(Configuration config,
Representation templateRepresentation) {
try {
// Instantiate the template with the character set of the template
// representation if it has been set, otherwise use UTF-8.
if (templateRepresentation.getCharacterSet() != null) {
return new Template("template", templateRepresentation
.getReader(), config, templateRepresentation
.getCharacterSet().getName());
}
return new Template("template", templateRepresentation.getReader(),
config, CharacterSet.UTF_8.getName());
} catch (IOException e) {
Context.getCurrentLogger().warning(
"Unable to get the template from the representation "
+ templateRepresentation.getLocationRef()
+ ". Error message: " + e.getMessage());
return null;
}
}
/**
* Returns a FreeMarker template from its name and a configuration.
*
* @param config
* The FreeMarker configuration.
* @param templateName
* The template name.
* @return The template or null if not found.
*/
public static Template getTemplate(Configuration config, String templateName) {
try {
return config.getTemplate(templateName);
} catch (IOException e) {
Context.getCurrentLogger().warning(
"Unable to get the template " + templateName
+ ". Error message: " + e.getMessage());
return null;
}
}
/** The template's data model. */
private volatile Object dataModel;
/** The FreeMarker template. */
private volatile Template template;
/**
* Constructor.
*
* @param templateRepresentation
* The FreeMarker template provided via a representation.
* @param config
* The FreeMarker configuration.
* @param mediaType
* The representation's media type.
*/
public TemplateRepresentation(Representation templateRepresentation,
Configuration config, MediaType mediaType) {
this(getTemplate(config, templateRepresentation), mediaType);
}
/**
* Constructor.
*
* @param templateRepresentation
* The FreeMarker template provided via a representation.
* @param config
* The FreeMarker configuration.
* @param dataModel
* The template's data model.
* @param mediaType
* The representation's media type.
*/
public TemplateRepresentation(Representation templateRepresentation,
Configuration config, Object dataModel, MediaType mediaType) {
this(getTemplate(config, templateRepresentation), dataModel, mediaType);
}
/**
* Constructor.
*
* @param templateRepresentation
* The FreeMarker template provided via a representation.
* @param mediaType
* The representation's media type.
*/
public TemplateRepresentation(Representation templateRepresentation,
MediaType mediaType) {
this(templateRepresentation, new Configuration(), mediaType);
}
/**
* Constructor. Uses a default FreeMarker configuration.
*
* @param templateRepresentation
* The FreeMarker template provided via a representation.
* @param dataModel
* The template's data model.
* @param mediaType
* The representation's media type.
*/
public TemplateRepresentation(Representation templateRepresentation,
Object dataModel, MediaType mediaType) {
this(templateRepresentation, new Configuration(), dataModel, mediaType);
}
/**
* Constructor.
*
* @param templateName
* The FreeMarker template's name. The full path is resolved by
* the configuration.
* @param config
* The FreeMarker configuration.
* @param mediaType
* The representation's media type.
*/
public TemplateRepresentation(String templateName, Configuration config,
MediaType mediaType) {
this(getTemplate(config, templateName), mediaType);
}
/**
* Constructor.
*
* @param templateName
* The FreeMarker template's name. The full path is resolved by
* the configuration.
* @param config
* The FreeMarker configuration.
* @param dataModel
* The template's data model.
* @param mediaType
* The representation's media type.
*/
public TemplateRepresentation(String templateName, Configuration config,
Object dataModel, MediaType mediaType) {
this(getTemplate(config, templateName), dataModel, mediaType);
}
/**
* Constructor.
*
* @param template
* The FreeMarker template.
* @param mediaType
* The representation's media type.
*/
public TemplateRepresentation(Template template, MediaType mediaType) {
super(mediaType);
this.template = template;
}
/**
* Constructor.
*
* @param template
* The FreeMarker template.
* @param dataModel
* The template's data model.
* @param mediaType
* The representation's media type.
*/
public TemplateRepresentation(Template template, Object dataModel,
MediaType mediaType) {
super(mediaType);
this.template = template;
this.dataModel = dataModel;
}
/**
* Returns the template's data model.
*
* @return The template's data model.
*/
public Object getDataModel() {
return this.dataModel;
}
/**
* Returns the FreeMarker template.
*
* @return The FreeMarker template.
*/
public Template getTemplate() {
return template;
}
/**
* Sets the template's data model.
*
* @param dataModel
* The template's data model.
* @return The template's data model.
*/
public Object setDataModel(Object dataModel) {
this.dataModel = dataModel;
return dataModel;
}
/**
* Sets the template's data model from a request/response pair. This default
* implementation uses a Resolver.
*
* @see Resolver
* @see Resolver#createResolver(Request, Response)
*
* @param request
* The request where data are located.
* @param response
* The response where data are located.
* @return The template's data model.
*/
public Object setDataModel(Request request, Response response) {
this.dataModel = new ResolverHashModel(Resolver.createResolver(request,
response));
return this.dataModel;
}
/**
* Sets the template's data model from a resolver.
*
* @param resolver
* The resolver.
* @return The template's data model.
*/
public Object setDataModel(Resolver<Object> resolver) {
this.dataModel = new ResolverHashModel(resolver);
return this.dataModel;
}
/**
* Sets the FreeMarker template.
*
* @param template
* The FreeMarker template.
*/
public void setTemplate(Template template) {
this.template = template;
}
/**
* Writes the datum as a stream of characters.
*
* @param writer
* The writer to use when writing.
*/
@Override
public void write(Writer writer) throws IOException {
if (this.template != null) {
try {
this.template.process(getDataModel(), writer);
} catch (TemplateException te) {
throw new IOException("Template processing error "
+ te.getMessage());
}
} else {
Context
.getCurrentLogger()
.warning(
"Unable to write the template representation. No template found.");
}
}
}