package org.nutz.lang.util;
import java.util.ArrayList;
import java.util.List;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.meta.Pair;
import static java.lang.String.*;
/**
* 简便的 Tag 实现
*
* @author zozoh(zozohtnt@gmail.com)
*/
public class Tag extends SimpleNode<HtmlToken> {
public static Tag tag(String name, String... attrs) {
Tag tag = new Tag();
tag.set(new HtmlToken().setName(name));
if (null != attrs)
for (String attr : attrs) {
if (null != attr && attr.length() > 1) {
char c = attr.charAt(0);
switch (c) {
case '.':
tag.addClass(attr.substring(1));
break;
case '#':
tag.id(attr.substring(1));
break;
default:
Pair<String> p = Pair.create(attr);
tag.attr(p.getName(), p.getValue());
}
}
}
return tag;
}
public static Tag text(String text) {
Tag tag = new Tag();
if (null != text) {
text = text.replace("&", "&");
text = text.replace("<", "<").replace(">", ">");
}
tag.set(new HtmlToken().setValue(text));
return tag;
}
public boolean isBlock() {
return get().isBlock();
}
public boolean isInline() {
return get().isInline();
}
public boolean isNoChild() {
return get().isNoChild();
}
public boolean isHtml() {
return "html".equalsIgnoreCase(get().getName());
}
public boolean isBody() {
return "body".equalsIgnoreCase(get().getName());
}
public boolean isChildAllInline() {
if (!get().isElement())
return false;
for (Node<HtmlToken> ht : this.getChildren())
if (ht.get().isBlock())
return false;
return true;
}
public String name() {
return get().getName();
}
public Tag attr(String name, String value) {
get().attr(name, value);
return this;
}
public Tag attr(String name, int value) {
return attr(name, String.valueOf(value));
}
public Tag addClass(String name) {
String cns = get().getAttrVal("class");
String[] nms = Strings.splitIgnoreBlank(cns, " ");
if (null == nms) {
get().attr("class", name);
} else {
if (!Lang.contains(nms, name)) {
get().attr("class", cns + " " + name);
}
}
return this;
}
public boolean hasClass(String name) {
String cns = get().getAttrVal("class");
if (null == cns || cns.length() < name.length())
return false;
return (" " + cns + " ").indexOf(" " + name + " ") != -1;
}
public Tag add(String tagName, String... attrs) {
Tag re = Tag.tag(tagName, attrs);
this.add(re);
return re;
}
public Tag id(String id) {
get().attr("id", id);
return this;
}
public String id() {
return get().getAttrVal("id");
}
public Tag setText(String text) {
this.add(Tag.text(text));
return this;
}
public List<Tag> childrenTag() {
List<Node<HtmlToken>> children = this.getChildren();
List<Tag> list = new ArrayList<Tag>(children.size());
for (Node<HtmlToken> nd : children) {
list.add((Tag) nd);
}
return list;
}
public String toString() {
if (get().isText())
return get().getValue();
StringBuilder sb = new StringBuilder();
if (isNoChild()) {
return format("<%s%s/>", name(), attributes2String());
} else if (isInline()) {
sb.append(format("<%s", name())).append(attributes2String()).append('>');
for (Node<HtmlToken> tag : getChildren())
sb.append(tag);
sb.append(format("</%s>", name()));
} else {
sb.append(format("<%s", name()));
sb.append(attributes2String()).append('>');
for (Node<HtmlToken> tag : getChildren()) {
if (tag.get().isBlock() || tag.get().isBody())
sb.append('\n');
sb.append(tag.toString());
}
if (!this.isChildAllInline())
sb.append('\n');
sb.append(format("</%s>", name()));
}
return sb.toString();
}
private String attributes2String() {
StringBuilder sb = new StringBuilder();
for (Pair<String> attr : get().getAttributes())
sb.append(' ').append(attr.toString());
return sb.toString();
}
}