Terminology
- (template) framework -- a set of classes and interfaces of mist4j library
- raw template -- a String with a special mark-up, that describes textual and substitutional data to be rendered
- source -- a class that performs substitutes rendering
- template (processor) -- a class that performs textual data rendering and source invocation
Public classes and interfaces
There are four public interfaces and one public class in mist4j framework.
IFastRenderer
The most basic is IFastRenderer interface. Any source should implement it.
Although the runtime invocation of method getOut() doesn't depend on interface implementation, it is kind of mandatory requirement (must). Really TemplateLoader accepts any class as a source specifying parameter, however it is declared to be Class<? extends IFastRenderer> (because of generic type erasure). Also it is possible to change interface ITemplate to accept any object as a parameter to avoid class cast. But changes like are strictly forbidden OO-concept.
Declared medhods:
- getOut -- should return the same writer as used by source object to render itself
ITemplate
This interface represents generated template classes.
Declared methods:
- process -- performs template rendering to Writer acquired from the given source
ITemplateSource
Implementation of this interface provides TemplateLoader with raw template data. ITemplateSource doesn't load data itself, instead it produces ITemplateResource instances.
Declared methods:
- getResource -- get ITemplateResource instance that will be used to access raw template
ITemplateResource
Instances implementing this interface are produced with getResource method of ITemplateSource implementation on TemplateLoader request.
In future ITemplateResource should become "update-aware". It means that TemplateLoader (or an object of higher level) could ask the instance of ITemplateResource if the data, taken last time, is "stale" (the underlying resource has been updated).
To ease the common-case implementation of this interface an inner static class Utils is built into interface.
Declared methods:
- getContent -- load raw template data from underlying resource
- Utils.loadContent -- a static method, loads the content of a given java.io.InputStream to String
TemplateLoader
This class is responsible for template loading. Is is initialized with ITemplateSource instance.
Public methods:
- loadTemplate -- returns instance of ITemplate for given template name, source class, and (optionally) writer class; raw template is accessed through ITemplateSource given on instance initialization
Examples
All-in-one example
public class TemplateLoaderTest {
// A simplest possible yet configurable implementation
public static class FakeResource implements ITemplateResource {
private final String text;
public FakeResource(String _text) {
text = _text;
}
@Override
public String getContent() throws IOException {
return text;
}
}
// A simplest possible yet configurable implementation
public static class FakeSource implements ITemplateSource {
// Can set this runtime or instantiation time
private String text;
public FakeSource(String _text) {
text = _text;
}
@Override
public ITemplateResource getResource(String fileName) {
return new FakeResource(text);
}
}
// A simple source example
public static class FakeRenderer implements IFastRenderer {
// After template processing we could check results
private StringWriter writer;
public FakeRenderer() {
writer = new StringWriter();
}
public void renderStub() {
writer.write("Cruel");
}
@Override
public Writer getOut() {
return writer;
}
}
public void testCommonTemplate() throws Exception {
// here we configure our fake resource-source with a raw template
FakeSource fakeSource = new FakeSource("Hello {stub} World");
// instantiate loader
// should have one loader per application context
// avoid reinitialization is a good practice
// however it gives no benefits in this case
TemplateLoader loader = new TemplateLoader(fakeSource);
// generate/instantiate template class
// should be cached to avoid performance issues
ITemplate template = loader.loadTemplate("fake", FakeRenderer.class);
// new source instance
FakeRenderer victim = new FakeRenderer();
// template processor invocation
// could be done many times
template.process(victim);
// result checking
Assert.assertEquals("Hello Cruel World", victim.getOut().toString(), "Incorrect template processing result");
}
}Typical web-application ITemplateSource implementation
public class TemplateSourceImpl implements ITemplateSource {
/**
* Resources directory, where templates are hold.
*/
private static final String TEMPLATES_DIR = "WEB-INF/templates/";
/**
* All template files has the name "<i>templateName</i><b>{@value} </b>". So
* it is the suffix.
*/
private static final String TEMPLATES_SUFFIX = ".html";
private final ServletContext loader;
public TemplateSourceImpl(ServletContext _loader) {
loader = _loader;
}
@Override
public ITemplateResource getResource(String fileName) {
String resourceName = TEMPLATES_DIR + fileName + TEMPLATES_SUFFIX;
return new TemplateResourceImpl(resourceName);
}
public class TemplateResourceImpl implements ITemplateResource {
private final String resourceName;
public TemplateResourceImpl(String _resourceName) {
resourceName = _resourceName;
}
@Override
public String getContent() throws IOException {
return Utils.loadContent(loader.getResourceAsStream(resourceName));
}
}
}