Tuesday, May 20, 2008

Use of EnumMap


     I have posted a few blogs explaining my idea of using Enum to create FormTagTemplate class which writes HTML tags. In this post, I'll use FormTagTemplate in CustomTagTemplate to sample the use of EnumMap.

     CustomTagTemplate has two custom tags: calendar and number. Calendar tag, as you can see from the image on the left, has one text field, one hidden field, and one image. When you click on the image or select the text field, a calendar will pop up. Number tag has one text field and one hidden field. It formats the number entered when the text field is onblur and unformat the number when the text field is onfocus. The actual raw value, however, is stored in the hidden field for both tags. Both tags require javascripts which I do not cover here. Calendar tag's javascript is my personal modification from Epoch JavaScript Calendar. I also added on a time picker with customizable time interval.

CustomTagTemplate.java

package net.yw.html;

import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;


/**
 * @author KWang
 *
 */
public enum CustomTagTemplate implements HTMLTagTemplate {
    calendar() {
        protected void setDefaults(){
            Map<String, Object> properties = new HashMap<String, Object>();
            properties.put("class", "right-align");
            properties.put("size", 29);
            this.defaults.put(FormTagTemplate.text, properties);
            
            properties = new HashMap<String, Object>();
            properties.put("src", "../images/calendar.gif");
            properties.put("class", "calendar");
            properties.put("alt", "");
            this.defaults.put(FormTagTemplate.img, properties);
        }
        
        public String doEnd() {
            return "";
        }

        public String doStart(Map<String, Object> propertyMap) throws HTMLTagException {
            StringBuffer sb = new StringBuffer();
            String name = propertyMap.get("name").toString();
            
            Map<String, Object> defaults = this.defaults.get(FormTagTemplate.text);
            defaults.putAll(propertyMap);
            if(defaults.containsKey("value"))
                defaults.remove("value");
            defaults.put("name", name + "_input");
            defaults.put("id", name + "_input");
            sb.append(FormTagTemplate.text.doStart(defaults));
            
            sb.append("\n");
            defaults = this.defaults.get(FormTagTemplate.img);
            defaults.put("name", name + "_input_img");
            defaults.put("id", name + "_input_img");
            sb.append(FormTagTemplate.img.doStart(defaults));
            
            sb.append("\n");
            defaults = new HashMap<String, Object>();
            defaults.put("id", name + "_input_fmt");
            sb.append(FormTagTemplate.div.doStart(defaults) + FormTagTemplate.div.doEnd());
            
            sb.append("\n");
            defaults = new HashMap<String, Object>();
            defaults.put("name", name);
            defaults.put("id", name);
            if(propertyMap.containsKey("value"))
                defaults.put("value", propertyMap.get("value"));
            sb.append(FormTagTemplate.hidden.doStart(defaults));
            
            boolean timepicker = propertyMap.containsKey("timepicker") ? Boolean.valueOf(propertyMap.get("timepicker").toString()) : false;
            int interval = propertyMap.containsKey("interval") ? Integer.valueOf(propertyMap.get("interval").toString()) : 15;
            sb.append("<script type=\"text/javascript\">");
            sb.append("epochCalendar('" + name + "', '" + name + "_input', " + timepicker + ", " + interval + ");");
            sb.append("</script>");
            return sb.toString();
        }
    },
    
    number(){
        protected void setDefaults(){
            Map<String, Object> properties = new HashMap<String, Object>();
            properties.put("class", "right-align");
            properties.put("size", 29);
            properties.put("maxlength", 11);
            this.defaults.put(FormTagTemplate.text, properties);
        }
        
        public String doEnd() {
            return "";
        }

        public String doStart(Map<String, Object> propertyMap) throws HTMLTagException {
            StringBuffer sb = new StringBuffer();
            String name = propertyMap.get("name").toString();
            String format = propertyMap.get("format").toString();
            
            Map<String, Object> defaults = this.defaults.get(FormTagTemplate.text);
            defaults.putAll(propertyMap);
            if(defaults.containsKey("value"))
                defaults.remove("value");
            defaults.put("name", name + "_input");
            defaults.put("id", name + "_input");
            defaults.put("onblur", "javascript:formatNumberFunc(this,'" + name + "','" + format + "');");
            defaults.put("onfocus", "javascript:unformatNumber(this,'" + format + "');");
            sb.append(FormTagTemplate.text.doStart(defaults));
            
            sb.append("\n");
            defaults = new HashMap<String, Object>();
            defaults.put("name", name);
            defaults.put("id", name);
            Object value = "0";
            if(propertyMap.containsKey("value"))
                value = propertyMap.get("value");
            if(value == null || StringUtils.isBlank(value.toString()) || !StringUtils.isNumeric(value.toString()))
                value = "0";
            defaults.put("value", value);
            sb.append(FormTagTemplate.hidden.doStart(defaults));
            
            sb.append("\n");
            sb.append("<script type=\"text/javascript\">");
            sb.append("$('" + name + "_input').value = formatNumberFunction(" + value + ", " + format + ");");
            sb.append("</script>");
            return sb.toString();
        }
    };
    
    protected EnumMap<FormTagTemplate, Map<String, Object>> defaults = new EnumMap<FormTagTemplate, Map<String, Object>>(FormTagTemplate.class);
    
    private CustomTagTemplate(){
        this.setDefaults();
    }
    
    protected abstract void setDefaults();

    public abstract String doEnd();

    public abstract String doStart(Map<String, Object> propertyMap) throws HTMLTagException;
}


     Of course you can add a calendar and a number function to the Utility class and create tag files in the same way as I did for input and select tag. However, it will be much easier if you just write it in pure tag file. Then you might wonder why go through all the trouble to write CustomTagTemplate? The answer is to use it for AJAX calls, which will be covered soon.

No comments: