package org.freehep.util.template;
import java.io.FilterReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/** A very simple template engine. The template engine takes input and transforms
* it by looking for tags in the document, and replacing them with values provided
* by a set of ValueProviders.
*
* Example of HTML template:
* <html>
* <head>
* <title>{v:title}</title>
* </head>
* <body>
* Welcome {v:name} to Simple Template Example
* <table>
* <tr bgcolor="d0d0d0"><th>Author</th><th>Title</th><th>Year</th></tr>
* <t:book>
* <tr>
* <td><a href="#">{v:author}</a></td>
* <td><a href="#">{v:title}</a></td>
* <td><a href="#">{v:year}</a></td>
* </tr>
* </t:book>
* </table>
* </body>
* </html>
*
* The design (although not the code) was inspired by the JByte template engine
* @link {http://javaby.sourceforge.net/}.
* @author tonyj
* @version $Id: TemplateEngine.java 8584 2006-08-10 23:06:37Z duns $
*/
public class TemplateEngine
{
/** Apply the template to a document.
* @param in The Reader from which the document will be read.
* @return A Reader from which the filtered document can be read.
*/
public Reader filter(Reader in)
{
return new TemplateReader(in,providers);
}
/** Add a value provider to the set of value providers
* @param p The ValueProvider to add
*/
public void addValueProvider(ValueProvider p)
{
providers.add(p);
}
/** Remove a value provider from the list of value providers.
* @param p The value provider to remove.
*/
public void removeValueProvider(ValueProvider p)
{
providers.remove(p);
}
private List providers = new ArrayList();
private static class TemplateReader extends FilterReader
{
TemplateReader(Reader in, List providers)
{
super(in);
this.providers = providers;
}
public int read() throws IOException
{
outer: for (;;)
{
if (subReader != null)
{
int c = subReader.read();
if (c >= 0) return c;
subReader = null;
}
if (templateIterator != null)
{
if (templateIterator.hasNext())
{
ValueProvider vp = (ValueProvider) templateIterator.next();
subReader = new TemplateReader(new StringReader(buf.toString()),Collections.singletonList(vp));
continue;
}
else
{
templateIterator = null;
buf.delete(0, buf.length());
}
}
if (state < 0)
{
int rc = buf.charAt(buf.length()+state++);
if (state == 0) buf.delete(0,buf.length());
return rc;
}
int c = in.read();
if (c<0)
{
state = -buf.length();
if (state == 0) return -1;
continue;
}
if (templateMarker > 0)
{
buf.append((char) c);
if (state == 0 && c == '<') state++;
else if (state == 1 && c == '/') state++;
else if (state > 1 && buf.charAt(state-1) == c) state++;
else state = 0;
if (state-1 == templateMarker) // Found end of template
{
String symb = buf.substring(3,templateMarker-1);
for (int i=0; i 2 && (template ? c!='>' : c!='}'))
{
state++;
buf.append((char) c);
}
else if (state > 2)
{
if (template)
{
// Everything must go into the string buffer until we
// find end of template
buf.append((char) c);
state++;
templateMarker = state;
state = 0;
}
else
{
String symb = buf.substring(3);
for (int i=0; i
Ads help maintain this website.