Tuesday, May 20, 2008

HTML Tag Template - Utility

     In my previous post, I wrote a FormTagTemplate which can write form tags. However, since I don't use TagSupport, I'll need a little utility class in order to actually use it to write tags in jsp files.

HTMLTagUtils.java

package net.yw.html;

import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;

/**
 * @author KWang
 * 
 */
public class HTMLTagUtils {

    // ResponseUtils.filter(String)
    public static String filter(String value) {
        if (value == null || value.length() == 0)
            return value;
        StringBuffer result = null;
        String filtered = null;
        for (int i = 0; i < value.length(); i++) {
            filtered = null;
            switch (value.charAt(i)) {
                case '<':
                    filtered = "&lt;";
                    break;
                case '>':
                    filtered = "&gt;";
                    break;
                case '&':
                    filtered = "&amp;";
                    break;
                case '"':
                    filtered = "&quot;";
                    break;
                case '\'':
                    filtered = "&#39;";
                    break;
            }

            if (result == null) {
                if (filtered != null) {
                    result = new StringBuffer(value.length() + 50);
                    if (i > 0) {
                        result.append(value.substring(0, i));
                    }
                    result.append(filtered);
                }
            } else {
                if (filtered == null) {
                    result.append(value.charAt(i));
                } else {
                    result.append(filtered);
                }
            }
        }

        return result == null ? value : result.toString();
    }

    public static String value(Object bean, String property, boolean escapeXml) throws IllegalAccessException, InvocationTargetException,
            NoSuchMethodException {
        String value = BeanUtils.getProperty(bean, property);
        if(value == null)
            return "";
        return escapeXml?filter(value):value;
    }

    @SuppressWarnings("unchecked")
    public static String select(Object bean, String property, String styleClass, Map<String, Object> properties,
            Object collections, String valueProperty, String labelProperty, String optionString) throws  HTMLTagException {
        if(StringUtils.isBlank(property))
            throw new HTMLTagException("property is missing");
        FormTagTemplate select = FormTagTemplate.select;
        properties.put("name", property);
        if(!properties.containsKey("id"))
            properties.put("id", properties.get("name"));
        if(StringUtils.isNotBlank(styleClass))
            properties.put("class", styleClass);
        
        StringBuffer sb = new StringBuffer(select.doStart(properties));
        
        //options
        FormTagTemplate option = FormTagTemplate.option;
        if(properties.containsKey("blank")){
            boolean blank = Boolean.parseBoolean(properties.get("blank").toString());
            if(blank){
                Map<String, Object> blankOp = new HashMap<String, Object>();
                blankOp.put("value", "");
                blankOp.put("label", "");
                sb.append(option.doStart(blankOp) + option.doEnd());
            }
        }
        if(collections != null){
            try {
                String value = bean == null ? "":value(bean, property, false);
                Map<String, Object> optionProp = new HashMap<String, Object>();
                if(collections instanceof Map){
                    for(Map.Entry<Object, Object> entry:((Map<Object, Object>)collections).entrySet()){
                        optionProp.put("value", entry.getKey().toString());
                        optionProp.put("label", entry.getValue().toString());
                        optionProp.put("selected", StringUtils.equals(value, entry.getKey().toString()));
                        sb.append(option.doStart(optionProp) + optionProp.get("label") + option.doEnd());
                    }
                }else if(collections instanceof Collection){
                    for(Object object:((Collection)collections)){
                        optionProp.put("value", StringUtils.isBlank(valueProperty)?object.toString():value(object, valueProperty, false));
                        optionProp.put("label", StringUtils.isBlank(labelProperty)?object.toString():value(object, labelProperty, false));
                        optionProp.put("selected", StringUtils.equals(value, optionProp.get("value").toString()));
                        sb.append(option.doStart(optionProp) + optionProp.get("label") + option.doEnd());
                    }
                }else if(collections.getClass().isArray()){
                    for(Object object:Arrays.asList((Object[])collections)){
                        if(object.getClass().isArray()){
                            int valueIndex = StringUtils.isNumeric(valueProperty)?Integer.valueOf(valueProperty):0;
                            int labelIndex = StringUtils.isNumeric(labelProperty)?Integer.valueOf(labelProperty):0;
                            optionProp.put("value", ((Object[])object)[valueIndex]);
                            optionProp.put("label", ((Object[])object)[labelIndex]);
                            optionProp.put("selected", StringUtils.equals(value, optionProp.get("value").toString()));
                            sb.append(option.doStart(optionProp) + optionProp.get("label") + option.doEnd());
                        }else{
                            optionProp.put("value", StringUtils.isBlank(valueProperty)?object.toString():value(object, valueProperty, false));
                            optionProp.put("label", StringUtils.isBlank(labelProperty)?object.toString():value(object, labelProperty, false));
                            optionProp.put("selected", StringUtils.equals(value, optionProp.get("value").toString()));
                            sb.append(option.doStart(optionProp) + optionProp.get("label") + option.doEnd());
                        }
                    }
                }
            } catch (IllegalAccessException e) {
                throw new HTMLTagException("Cannot get value of " + property + " from " + bean );
            } catch (InvocationTargetException e) {
                throw new HTMLTagException("Cannot get value of " + property + " from " + bean );
            } catch (NoSuchMethodException e) {
                throw new HTMLTagException("Cannot get value of " + property + " from " + bean );
            }
        }
        
        if(StringUtils.isNotBlank(optionString))
            sb.append(optionString);
        sb.append(select.doEnd());
        return sb.toString();
    }
    
    public static String input(Object bean, String property, String styleClass, String type, Map<String, Object> properties) throws HTMLTagException{
        if(StringUtils.isBlank(property))
            throw new HTMLTagException("property is missing");
        FormTagTemplate tag = FormTagTemplate.valueOf(type);
        if(tag == null)
            throw new HTMLTagException("tag " + type + " not found!");
        else if(tag.equals(FormTagTemplate.select) || tag.equals(FormTagTemplate.option))
            throw new HTMLTagException("Please use select for select/option type tag!");
        else if(tag.equals(FormTagTemplate.div))
            throw new HTMLTagException("Please use div tag directly in page!");

        properties.put("name", property);
        if(!properties.containsKey("id"))
            properties.put("id", properties.get("name"));
        if(StringUtils.isNotBlank(styleClass))
            properties.put("class", styleClass);

        try {
            String value = bean == null || tag.equals(FormTagTemplate.file) ? "":value(bean, property, false);
            switch(tag){
                case radio:
                    for(String key:properties.keySet()){
                        if(StringUtils.equalsIgnoreCase(key, "value")){
                            String compareValue = properties.get(key).toString();
                            properties.put("checked", Boolean.valueOf(StringUtils.equals(value, compareValue)));
                            break;
                        }
                    }
                    break;
                case checkbox:
                    if(!properties.containsKey("value"))
                        properties.put("value", "on");
                    properties.put("checked", Boolean.valueOf(value));
                    break;
                default:
                    properties.put("value", value);
                    break;
            }
            
            StringBuffer sb = new StringBuffer(tag.doStart(properties));
            if(tag.equals(FormTagTemplate.textarea) || tag.equals(FormTagTemplate.div))
                sb.append(value + tag.doEnd());
            return sb.toString();
        } catch (IllegalAccessException e) {
            throw new HTMLTagException("Cannot get value of " + property + " from " + bean );
        } catch (InvocationTargetException e) {
            throw new HTMLTagException("Cannot get value of " + property + " from " + bean );
        } catch (NoSuchMethodException e) {
            throw new HTMLTagException("Cannot get value of " + property + " from " + bean );
        }
    }
}


     The utility only has four functions. filter() is identical to ResponseUtils.filter() in Struts. value() retrieves the String value of a property in a bean. select() and input() is used in select and input tag files in my next post.

No comments: