/* * Created on Jan 28, 2005 * */ package net.sf.thingamablog.generator; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Vector; public class TemplateProcessor { private static final String LT = "<"; private static final String GT = ">"; private static final String END_LT = "</"; private static final String TAG_LT = LT + '$'; private static final String TAG_GT = '$' + GT; public String processTemplate(String tmpl, TemplateContainer root) { List temps = parseContainers(tmpl, root); for(Iterator it = temps.iterator(); it.hasNext();) { String curTmp = it.next().toString(); StringWriter sw = new StringWriter(curTmp.length() * 2); try { writeContainer(curTmp, root, sw); } catch(IOException ioe){} StringBuffer buf = sw.getBuffer(); tmpl = replace(curTmp, buf.substring(0, buf.length()), tmpl); } return tmpl; } public void writeContainer(String tmpl, TemplateContainer cont, Writer writer) throws IOException { cont.initialize(parseAttributes(tmpl, cont)); if(cont.isVisible()) { do { String result = processVariables(stripOffTags(tmpl, cont), cont); if(cont.prefix() != null) writer.write(cont.prefix()); writer.write(processContainers(result, cont)); if(cont.postfix() != null) writer.write(cont.postfix()); } while(cont.processAgain()); } } public List parseContainers(String tmpl, TemplateContainer tc) { int _pos = 0; Vector temps = new Vector(); String containerStart = LT + tc.getName(); String closeTag = END_LT + tc.getName() + GT; while(tmpl.indexOf(containerStart, _pos) > -1) { int s = tmpl.indexOf(containerStart, _pos);//open tag begin if(s < 0)//not found continue; _pos = s + tc.getName().length() + 1; //update pos; char ch = tmpl.charAt(_pos); if(ch != '>' && !Character.isWhitespace(ch)) continue; //this isn't the right tag, //it only starts like the one we're looking for //System.out.println("After tag = " + t.charAt(pos)); //now we have to find the end ">" of the open tag int otEnd = tmpl.indexOf(GT, _pos); if(otEnd < 0)//incomplete tag continue; _pos = otEnd; int e = tmpl.indexOf(closeTag, _pos); if(e < 0)//incomple tag continue; e += closeTag.length(); _pos = e; temps.add(tmpl.substring(s, e)); } return temps; } private String stripOffTags(String t, TemplateContainer tc) { int s = t.indexOf(GT); //end of open tag int e = t.indexOf(END_LT + tc.getName() + GT);//end of close tag if(s < 0 || e < 0 || (s + 1) >= t.length()) return t; return t.substring(s + 1, e); } private String processVariables(String tmpl, TemplateContainer tc) { List list = tc.getTags(); if(list != null) { Iterator it = list.iterator(); while(it.hasNext()) { TemplateTag tag = (TemplateTag)it.next(); tmpl = parseVariable(tmpl, tag, tc.getValueForTag(tag)); } } return tmpl; } private String processContainers(String tmpl, TemplateContainer tc) { List list = tc.getContainers(); if(list != null) { Iterator it = list.iterator(); while(it.hasNext()) { tmpl = processTemplate(tmpl, (TemplateContainer)it.next()); } } return tmpl; } private String parseVariable(String tmpl, TemplateTag tag, Object obj) { int _pos = 0; String attribsStart = TAG_LT; String attribsEnd = TAG_GT; String tagStart = attribsStart + tag.getName(); while((_pos = tmpl.indexOf(tagStart, _pos)) > -1) { int end = tmpl.indexOf(attribsEnd, _pos) + attribsEnd.length(); if(end < _pos)//no more return tmpl; String var = tmpl.substring(_pos, end); int nameLen = tag.getName().length(); int normalLen = attribsStart.length() + nameLen + attribsEnd.length(); if(var.length() > normalLen) { //this tag should have whitespace between the tag name and //attribute list because it's longer than //the normal, no-attribute, length. char c = var.charAt(attribsStart.length() + nameLen); if(!Character.isWhitespace(c)) { //System.out.println(c + " - " + tag.getName() + " - " + var); //No whitespace found so //this isn't the right tag, it only starts //like the one we're looking for, so pass it over _pos = end; continue; } } Hashtable ht = parseAttributes(var, tag); String val = tag.process(obj, ht); tmpl = replace(var, val, tmpl); } return tmpl; } private Hashtable parseAttributes(String t, TemplateElement te) { Hashtable defaults = te.getDefaultAttributes(); if(defaults == null)//don't allow null attributes defaults = new Hashtable();//empty attributes Hashtable ht = new Hashtable(defaults);//copy defaults String attribsStart = getAttribsStart(te) + te.getName(); String attribsEnd = getAttribsEnd(te); int s = t.indexOf(attribsStart, 0);//open tag begin if(s == -1)//not found return ht; int e = t.indexOf(attribsEnd, s + attribsStart.length()); if(e == -1 || e == (s + attribsStart.length()))//no attributes given, use defaults return ht; String attribs = t.substring(s + attribsStart.length(), e).trim(); //System.out.println(attribs); attribs = " " + attribs;//ensure the first attrib has a prefixed space char ws[] = {' ', '\n', '\t'}; for(Enumeration eEnum = ht.keys(); eEnum.hasMoreElements();) { String key = eEnum.nextElement().toString(); int p = 0; for(int i = 0; i < ws.length; i++) { p = attribs.indexOf(ws[i] + key); if(p != -1) break; } if(p == -1)//attribute wasn't found, default will be used continue; //skip over the space and attribute name p += key.length() + 1; try { //iterate thru whitespace till we hit equals while(Character.isWhitespace(attribs.charAt(p++))); if(attribs.charAt(--p) != '=') break; //iterate thru whitespace till we hit opening quote while(Character.isWhitespace(attribs.charAt(++p))); if(attribs.charAt(p) != '\"') break; int end = attribs.indexOf("\"", p + 1);//end quote if(end == -1) break;//no closing quote //FIXED with trim() this screws up attribs like glue=", " //String val = attribs.substring(p, end).trim(); String val = attribs.substring(p, end); //remove quotes if(val.startsWith("\"") /*&& val.length() > 1*/) val = val.substring(1, val.length()); if(val.endsWith("\"") /*&& val.length() > 1*/) val = val.substring(0, val.length() - 1); ht.put(key, val); //System.out.println(key + " = " +val); } catch(IndexOutOfBoundsException ex) { break; } } return ht; } private String replace(String var, String val, String tmpl) { if(var.equals("") || var == null) return tmpl; StringBuffer sb = new StringBuffer(val.length() + tmpl.length()); sb.append(tmpl); while(sb.indexOf(var) != -1 && !var.equals(val)) { int s = sb.indexOf(var); int e = s + var.length(); sb.delete(s, e); sb.insert(s, val); } return sb.substring(0, sb.length()); } private String getAttribsStart(TemplateElement te) { if(te instanceof TemplateTag) return TAG_LT; return LT; } private String getAttribsEnd(TemplateElement te) { if(te instanceof TemplateTag) return TAG_GT; return GT; } }