Wednesday, March 3, 2010

YAHB

private class YAHB {
StringBuilder buf;
LinkedList openTags = new LinkedList();
boolean hasIncompleteTag = false;

public YAHB() {
buf = new StringBuilder();
}

public String toString() {
return buf.toString();
}

// Requires close
public YAHB tag(String tag) {
if (hasIncompleteTag)
endTag();
buf.append("<");
buf.append(tag);
openTags.addLast(tag);
hasIncompleteTag = true;
return this;
}
// Requires close
public YAHB tag(String tag, String name) {
return tag(tag).attr("id", name).attr("name", name);
}

public YAHB endTag() {
assert(hasIncompleteTag);
buf.append(">");
hasIncompleteTag = false;
return this;
}

public YAHB close() {
if (hasIncompleteTag)
endTag();
String tag = openTags.removeLast();
buf.append(" buf.append(tag);
buf.append(">");
return this;
}

// Full close
public String done() {
while (openTags.size() > 0)
close();
return buf.toString();
}

public YAHB attr(String attr, Object value) {
assert(hasIncompleteTag);
if (value == null)
return this;

buf.append(" ");
buf.append(attr);
buf.append("='");
buf.append(value.toString());
buf.append("'");
return this;
}

public YAHB text(String text) {
if (text != null)
buf.append(text);
return this;
}

// Closes
public YAHB value(String text) {
if (hasIncompleteTag)
endTag();
text(text);
close();
return this;
}

// these conveniences may not work for everyone
// if you add to this, be sure they're actually convenient
// these progress from most general to least


// Requires close
public YAHB form(String name, String url) {
return tag("form", name)
.attr("method", "POST");
}
// Requires close
public YAHB form(String name) {
return form(name, "#");
}

// Requires close
public YAHB input(String name, String type) {
return tag("input", name).attr("type", type);
}

// Makes a label and opens a <p>
// Requires close
public YAHB field(String fieldId, String label) {
return tag("label").attr("for", fieldId).text(label).text(": ").close()
.tag("p").clazz("field");
}

public YAHB clazz(String clazz) {
return attr("class", clazz);
}

// labels and values are processed in lockstep ("dual comprehension")
// the word 'value' is overloaded, yes it's confusing
public YAHB select(String selectId, String def, List