Tuesday, May 20, 2008

HTML Tag Template - Enum

     In my previous post, I created an interface for HTML Tags. Now,I'll create FormTagTemplate implementing HTMLTagTemplate which is for general form tags:

FormTagTemplate.java

package net.yw.html;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

/**
 * @author KWang
 * 
 */
public enum FormTagTemplate implements HTMLTagTemplate {

    button("input") {
        protected void additionalSetting() {
            this.standardAttributes.addAll(Arrays.asList("tabindex", "accesskey"));
            this.requiredAttributes.add("name");
            this.optionalAttributes.addAll(Arrays.asList("disabled", "size", "value"));
            this.eventAttributes.addAll(Arrays.asList("onfocus", "onblur", "onselect", "onchange"));
        }
    },

    checkbox("input") {
        protected void additionalSetting() {
            this.standardAttributes.addAll(Arrays.asList("tabindex", "accesskey"));
            this.requiredAttributes.addAll(Arrays.asList("name", "value"));
            this.optionalAttributes.addAll(Arrays.asList("checked", "disabled", "size"));
            this.eventAttributes.addAll(Arrays.asList("onfocus", "onblur", "onselect", "onchange"));
        }
    },

    file("input") {
        protected void additionalSetting() {
            this.standardAttributes.addAll(Arrays.asList("tabindex", "accesskey"));
            this.requiredAttributes.add("name");
            this.optionalAttributes.addAll(Arrays.asList("accept", "size"));
            this.eventAttributes.addAll(Arrays.asList("onfocus", "onblur", "onselect", "onchange"));
        }
    },

    hidden("input") {
        protected void additionalSetting() {
            this.standardAttributes.addAll(Arrays.asList("tabindex", "accesskey"));
            this.requiredAttributes.add("name");
            this.optionalAttributes.add("value");
            this.eventAttributes.addAll(Arrays.asList("onfocus", "onblur", "onselect", "onchange"));
        }
    },

    image("input") {
        protected void additionalSetting() {
            this.standardAttributes.addAll(Arrays.asList("tabindex", "accesskey"));
            this.requiredAttributes.add("name");
            this.optionalAttributes.addAll(Arrays.asList("align", "alt", "disabled", "size", "src",
                    "value"));
            this.eventAttributes.addAll(Arrays.asList("onfocus", "onblur", "onselect", "onchange"));
        }
    },

    password("input") {
        protected void additionalSetting() {
            this.standardAttributes.addAll(Arrays.asList("tabindex", "accesskey"));
            this.requiredAttributes.add("name");
            this.optionalAttributes.addAll(Arrays.asList("disabled", "size", "value"));
            this.eventAttributes.addAll(Arrays.asList("onfocus", "onblur", "onselect", "onchange" ));
        }
    },

    radio("input") {
        protected void additionalSetting() {
            this.standardAttributes.addAll(Arrays.asList("tabindex", "accesskey"));
            this.requiredAttributes.addAll(Arrays.asList("name", "value"));
            this.optionalAttributes.addAll(Arrays.asList("checked", "disabled", "size"));
            this.eventAttributes.addAll(Arrays.asList("onfocus", "onblur", "onselect", "onchange"));
        }
    },

    reset("input") {
        protected void additionalSetting() {
            this.standardAttributes.addAll(Arrays.asList("tabindex", "accesskey"));
            this.optionalAttributes.addAll(Arrays.asList("disabled", "name", "size", "value"));
            this.eventAttributes.addAll(Arrays.asList("onfocus", "onblur", "onselect", "onchange"));
        }
    },

    submit("input") {
        protected void additionalSetting() {
            this.standardAttributes.addAll(Arrays.asList("tabindex", "accesskey"));
            this.optionalAttributes.addAll(Arrays.asList("disabled", "name", "size", "value"));
            this.eventAttributes.addAll(Arrays.asList("onfocus", "onblur", "onselect", "onchange"));
        }
    },

    text("input") {
        protected void additionalSetting() {
            this.standardAttributes.addAll(Arrays.asList("tabindex", "accesskey"));
            this.requiredAttributes.add("name");
            this.optionalAttributes.addAll(Arrays.asList("disabled", "maxlength", "readonly", "size",
                    "value"));
            this.eventAttributes.addAll(Arrays.asList("onfocus", "onblur", "onselect", "onchange"));
        }
    },

    select("select") {
        protected void additionalSetting() {
            this.standardAttributes.addAll(Arrays.asList("tabindex", "accesskey"));
            this.optionalAttributes.addAll(Arrays.asList("disabled", "multiple", "name", "size"));
            this.eventAttributes.addAll(Arrays.asList("onfocus", "onblur", "onchange"));
        }
    },

    option("option") {
        protected void additionalSetting() {
            this.optionalAttributes.addAll(Arrays.asList("disabled", "label", "selected", "value"));
        }
    },

    textarea("textarea") {
        protected void additionalSetting() {
            this.standardAttributes.addAll(Arrays.asList("tabindex", "accesskey"));
            this.requiredAttributes.addAll(Arrays.asList("cols", "rows"));
            this.optionalAttributes.addAll(Arrays.asList("disabled", "name", "readonly"));
            this.eventAttributes.addAll(Arrays.asList("onfocus", "onblur", "onselect", "onchange"));
        }
    },

    div("div") {
        protected void additionalSetting() {
            this.optionalAttributes.add("align");
        }
    },

    img("img") {
        protected void additionalSetting() {
            this.requiredAttributes.addAll(Arrays.asList("alt", "src"));
            this.optionalAttributes.addAll(Arrays.asList("align", "border", "height", "hspace", "ismap",
                    "longdesc", "usemap", "vspace", "width"));
        }
    };

    protected String tagName;

    protected String type;

    protected List<String> standardAttributes = new ArrayList<String>(Arrays.asList("id", "class",
            "title", "style", "dir", "lang"));

    protected List<String> requiredAttributes = new ArrayList<String>();

    protected List<String> optionalAttributes = new ArrayList<String>();

    protected List<String> eventAttributes = new ArrayList<String>(Arrays.asList("onclick", "ondbclick",
            "onhelp", "onmousedown", "onmouseup", "onmouseover", "onmousemove", "onmouseout", "onkeypress",
            "onkeydown", "onkeyup"));

    private FormTagTemplate(String tagName) {
        this.tagName = tagName.toLowerCase();
        this.type = this.toString().equals(this.tagName) ? null : this.toString();
        this.additionalSetting();
    }

    protected abstract void additionalSetting();

    public List<String> getAcceptableAttributes() {
        List<String> acceptables = new ArrayList<String>(this.standardAttributes);
        acceptables.addAll(this.requiredAttributes);
        acceptables.addAll(this.optionalAttributes);
        acceptables.addAll(this.eventAttributes);
        return Collections.unmodifiableList(acceptables);
    }

    private Map<String, String> filterProperties(Map<String, Object> propertyMap) {
        Map<String, String> properties = new HashMap<String, String>();
        if (propertyMap != null && !propertyMap.isEmpty()) {
            List<String> list = this.getAcceptableAttributes();
            for (Map.Entry<String, Object> entry : propertyMap.entrySet()) {
                String key = entry.getKey().toLowerCase();
                if (list.contains(key)) {
                    Object value = entry.getValue();
                    if (value instanceof Boolean) {
                        if (((Boolean) value).booleanValue())
                            properties.put(key, key);
                    } else
                        properties.put(key, HTMLTagUtils.filter(value.toString()));
                }
            }
        }
        return properties;
    }

    public String doStart(Map<String, Object> propertyMap) throws HTMLTagException {
        Map<String, String> properties = filterProperties(propertyMap);
        if (!properties.keySet().containsAll(this.requiredAttributes))
            throw new HTMLTagException(this.toString() + ": One or more required field(s) is/are missing: "
                    + this.requiredAttributes.toString());

        StringBuffer sb = new StringBuffer("<" + this.tagName + " ");
        if (StringUtils.isNotBlank(this.type))
            sb.append("type=\"" + this.type + "\" ");
        for (Map.Entry<String, String> entry : properties.entrySet())
            sb.append(entry.getKey() + "=\"" + entry.getValue() + "\" ");
        switch (this) {
            case select:
            case option:
            case textarea:
            case div:
                sb.append(">");
                break;

            default:
                sb.append("/>");
                break;
        }
        return sb.toString();
    }

    public String doEnd() {
        switch (this) {
            case select:
            case option:
            case textarea:
            case div:
                return "</" + this.tagName + ">";

            default:
                return "";
        }
    }
}


     As you can see from the code above, each tag's properties will be filtered so that only acceptable properties will be written. And each tag's unique property set is done by overwritten additionalSetting(). doStart() and doEnd() take advantage of the Enum by using switch to customize how to write the tag.

     In my next post, I'll talk about the utility I use in Tag File.

No comments: