package com.google.sitebricks.rendering.control; import java.util.List; import java.util.Map; import com.google.sitebricks.Respond; /** * @author Dhanji R. Prasanna (dhanji@gmail com) */ class EmbeddedRespond implements Respond { private static final String BODY_BEGIN = "<body"; private static final String BODY_END = "</body>"; private static final char NOT_IN_QUOTE = '\0'; // Memo fields. private String body; private final Map<String, ArgumentWidget> arguments; private final Respond delegate; private List<String> errors; public EmbeddedRespond(Map<String, ArgumentWidget> arguments, Respond respond) { this.arguments = arguments; this.delegate = respond; } public String toHeadString() { if (null == body) { //extract and store extract(delegate.toString()); } //we discard the <head> tag rendered in the child page and //instead return only what was directly rendered with writeToHead() return delegate.getHead(); } //state machine extracts <body> tag content private void extract(String htmlDoc) { //now extract the contents of <body>... int bodyStart = htmlDoc.indexOf(BODY_BEGIN) + BODY_BEGIN.length(); //scan for end of the <body> start tag (beginning of body content) char quote = NOT_IN_QUOTE; for (int body = bodyStart; body < htmlDoc.length(); body++) { final char c = htmlDoc.charAt(body); if (isQuoteChar(c)) { if (quote == NOT_IN_QUOTE) quote = c; else if (quote == c) quote = NOT_IN_QUOTE; } if ('>' == c && NOT_IN_QUOTE == quote) { bodyStart = body + 1; break; } } int bodyEnd = htmlDoc.indexOf(BODY_END, bodyStart); //if there was no body tag, just embed whatever was rendered directly if (-1 == bodyEnd) { EmbeddedRespond.this.body = htmlDoc; } else EmbeddedRespond.this.body = htmlDoc.substring(bodyStart, bodyEnd); } private static boolean isQuoteChar(char c) { return '"' == c || '\'' == c; } public void write(String text) { delegate.write(text); } public HtmlTagBuilder withHtml() { return delegate.withHtml(); } public void write(char c) { delegate.write(c); } public void require(String require) { delegate.require(require); } public void redirect(String to) { delegate.redirect(to); } public void writeToHead(String text) { delegate.writeToHead(text); } public void chew() { delegate.chew(); } public String getRedirect() { return delegate.getRedirect(); } public String getContentType() { return delegate.getContentType(); } public ArgumentWidget include(String name) { return arguments.get(name); } public String getHead() { return delegate.getHead(); } public void clear() { delegate.clear(); } @Override public Object pageObject() { return delegate.pageObject(); } @Override public List<String> getErrors() { return this.errors; } @Override public void setErrors(List<String> errors) { this.errors = errors; } @Override public String toString() { if (null == body) { extract(super.toString()); } return body; } }