/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.empire.jsf2.controls;

import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UIData;
import javax.faces.component.UIInput;
import javax.faces.component.behavior.ClientBehaviorHolder;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.event.PhaseId;

import org.apache.empire.commons.ObjectUtils;
import org.apache.empire.commons.OptionEntry;
import org.apache.empire.commons.Options;
import org.apache.empire.commons.StringUtils;
import org.apache.empire.data.Column;
import org.apache.empire.data.DataType;
import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.ItemNotFoundException;
import org.apache.empire.exceptions.UnexpectedReturnValueException;
import org.apache.empire.jsf2.app.TextResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class InputControl
{

    private static final Logger log                   = LoggerFactory.getLogger(InputControl.class);
    
    // format attributes
    public static final String  FORMAT_NULL                   = "null:";
    public static final String  FORMAT_NULL_ATTRIBUTE         = "format:null";
    public static final String  FORMAT_VALUE_STYLES           = "valueStyles";
    public static final String  FORMAT_VALUE_STYLES_ATTRIBUTE = "format:valueStyles";
    
    // HTML-TAGS
    public static final String  HTML_TAG_DIV          = "div"; 
    public static final String  HTML_TAG_SPAN         = "span";
    public static final String  HTML_TAG_TABLE        = "table";
    public static final String  HTML_TAG_TR           = "tr";
    public static final String  HTML_TAG_TD           = "td";
    public static final String  HTML_TAG_INPUT        = "input";
    public static final String  HTML_TAG_LABEL        = "label";
    
    // HTML-ATTRIBUTES
    public static final String  HTML_ATTR_ID          = "id";
    public static final String  HTML_ATTR_CLASS       = "class";
    public static final String  HTML_ATTR_STYLE       = "style";
    public static final String  HTML_ATTR_TYPE        = "type";
    public static final String  HTML_ATTR_DISABLED    = "disabled";
    public static final String  HTML_ATTR_CHECKED     = "checked";
    
    // HTML
    public static String HTML_EXPR_NBSP = "&nbsp;";
    
    // style classes
    public static final String STYLECLASS_REQUIRED    = "eInpReq";

    public InputControl()
    {
        InputControl.log.info("InputControl of class {} created.", getClass().getName());
    }

    /**
     * This interface allows access to a value and its metainformation
     * used with the renderData function
     */
    public interface ValueInfo
    {
        Column getColumn();

        Options getOptions();

        Object getValue(boolean evalExpression);

        String getFormat(); // Custom Formatting options specific to each InputControl-type

        Locale getLocale();

        String getText(String key);

        TextResolver getTextResolver();

        String getStyleClass(String addlStyle);

        /*
        Object getNullValue();
        String getOnclick();
        String getOndblclick();
        String getCssClass();
        String getCssStyle();
        String getId();
        */
        
        boolean isInsideUIData();
    }

    /**
     * This interface extends the value information by information about the input control
     * used with the renderInput function
     */
    public interface InputInfo extends ValueInfo
    {
        // perform action 
        void setValue(Object value);

        void validate(Object value);

        boolean isRequired();

        boolean isDisabled(); // disabled or readOnly

        boolean isFieldReadOnly(); // not disabled only readOnly (for input[type=text] only!)
        // input

        String getInputId();

        boolean hasError();

        /*
        String getName();
        String getTabindex();
        String getAccesskey();
        boolean isValid(); // Indicates whether the value supplied is valid
        String getOnchange();
        String getOnfocus();
        String getOnblur();
        */
        Object getAttribute(String name); /* gets tag attribute only */

        Object getAttributeEx(String name); /* check Column attributes too, and resolves references to other columns. */
    }

    private String name;

    protected InputControl(String name)
    {
        this.name = name;
    }

    public final String getName()
    {
        return this.name;
    }

    public String getLabelForId(InputInfo ii)
    {
        return ii.getInputId();
    }
    
    /**
     * Flag indicating whether child components are being created
     */
    private boolean creatingComponents = false;
    public boolean isCreatingComponents()
    {
        return this.creatingComponents;
    }
    
    /* createInput */ 
    public void createInput(UIComponent comp, InputInfo ii, FacesContext context)
    {   // createInputComponents
        List<UIComponent> children = comp.getChildren();
        try {
            this.creatingComponents = true;
            createInputComponents(comp, ii, context, children);
            // check
            boolean resetChildId = ii.isInsideUIData();
            if (resetChildId && log.isDebugEnabled())
            {   // Debug-Info only   
                UIComponent c1 = comp.getChildren().get(0);
                String clientId = c1.getClientId();
                log.debug("Performing ChildId-reset for {}", clientId);
            }
            // add attached objects
            UIComponent parent = comp;
            while (!(parent instanceof UIInput))
                parent = parent.getParent();
            for (UIComponent child : children)
            {   // reset child-id
                if (resetChildId && child.getId()!=null)
                    child.setId(child.getId());
                // check type
                if (!(child instanceof ClientBehaviorHolder))
                    continue;
                // add attached objects
                addAttachedObjects(parent, context, ii, ((UIComponentBase)child));
            }
        } finally {
            this.creatingComponents = false;
        }
    }
    
    /**
     * Renders the control value with a surrounding HTML tag, if a tagName is supplied
     * @param comp the JSF component
     * @param tagName the tag name of the HTML wrapper tag (optional)
     * @param styleClass the style class of the HTML wrapper tag (optional)
     * @param tooltip the title of the HTML wrapper tag (optional)
     * @param vi the value info
     * @param context the FacesContext
     * @throws IOException
     */
    public void renderValue(UIComponent comp, String tagName, String styleClass, String tooltip, ValueInfo vi, FacesContext context)
        throws IOException
    {
        // writer
        ResponseWriter writer = context.getResponseWriter();
        // has tag?
        if (tagName!=null)
        {   // write start tag
            writer.startElement(tagName, comp);
            if (hasFormatOption(vi, FORMAT_VALUE_STYLES, FORMAT_VALUE_STYLES_ATTRIBUTE))
                styleClass = addDataValueStyle(vi, vi.getValue(true), styleClass);
            if (StringUtils.isNotEmpty(styleClass))
                writer.writeAttribute("class", styleClass, null);
            if (StringUtils.isNotEmpty(tooltip))
                writer.writeAttribute("title", tooltip, null);
            // style
            Object style = comp.getAttributes().get("style");
            if (style!=null)
                writer.writeAttribute("style", style, null);
        }
        // render Value
        renderValue(vi, writer);
        // has tag?
        if (tagName!=null)
        {   // write end tag
            writer.endElement(tagName);
        }
    }
    
    /**
     * Renders the control value without a surrounding tag (Text only)
     * @param vi the value info
     * @param writer the output writer
     * @throws IOException
     */
    public void renderValue(ValueInfo vi, ResponseWriter writer)
        throws IOException
    {
        String text = formatValue(vi);
        writer.append((StringUtils.isEmpty(text) ? HTML_EXPR_NBSP : text));
    }

    /**
     * Renders the input element(s) for editing the underlying record value 
     * @param comp the JSF component
     * @param ii the input info
     * @param context the FacesContext
     * @throws IOException
     */
    public void renderInput(UIComponent comp, InputInfo ii, FacesContext context)
        throws IOException
    {
        // Encode all
        for (UIComponent child : comp.getChildren())
        {   // render
            if (child.isRendered())
                child.encodeAll(context);
        }
    }
    
    public void updateInputState(UIComponent parent, InputInfo ii, FacesContext context, PhaseId phaseId)
    {
        List<UIComponent> cl = parent.getChildren(); 
        if (cl.isEmpty())
            return;
        updateInputState(cl, ii, context, phaseId);
        // update attached objects
        List<UIComponent> children = parent.getChildren();
        while (!(parent instanceof UIInput))
            parent = parent.getParent();
        for (UIComponent child : children)
        {   // check type
            if (!(child instanceof ClientBehaviorHolder))
                continue;
            // update attached objects
            updateAttachedObjects(parent, context, ii, ((UIComponentBase)child));
        }
    }
    
    public void postUpdateModel(UIComponent comp, InputInfo ii, FacesContext fc)
    {
        UIInput input = getInputComponent(comp);
        if (input == null)
            return; /* May want to override this */
        // Clear submitted value
        clearSubmittedValue(input);
    }
    
    public Object getInputValue(UIComponent comp, InputInfo ii, boolean submitted)
    {
        UIInput input = getInputComponent(comp);
        if (input == null)
        {   // throw new ObjectNotValidException(this);
            return null; // ignore
        }
        
        // Get value from Input
        Object value;
        if (submitted)
        {   // check disabled
            if (ii.isDisabled())
            { // Ignore submitted value
                InputControl.log.debug("Ignoring submitted value for disabled field {}.", ii.getColumn().getName());
                input.setSubmittedValue(null);
                // throw new FieldIsReadOnlyException(ii.getColumn());
                return null;
            }
            // get submitted value
            value = input.getSubmittedValue();
            if (value == null && input.isLocalValueSet()) // required for MyFaces!
            {   // take local value
                if (log.isDebugEnabled())
                    log.debug("No submitted value but local value available for InputComponent {}. Local value is '{}'", input.getClientId(), input.getLocalValue());
                value = input.getLocalValue();
                if (value == null)
                {   // Empty-String
                    value = "";
                }
            }
            // debug
            if (log.isDebugEnabled())
                log.debug("Submitted value for {} is {}", comp.getClientId(), value);
        }
        else
        {   // the current value
            value = input.getValue();
        }
        return value;
    }

    public Object getConvertedValue(UIComponent comp, InputInfo ii, Object submittedValue)
    {
        // Value supplied?
        if (submittedValue != null)
        {   // Save submitted value in request-map
            FacesContext fc = FacesContext.getCurrentInstance();
            Map<String, Object> reqMap = fc.getExternalContext().getRequestMap();
            // Save submitted value
            UIInput input = getInputComponent(comp);
            String clientId = input.getClientId();
            if (reqMap.containsKey(clientId))
            {   Object oldValue =  reqMap.get(clientId);
                if (ObjectUtils.compareEqual(oldValue, submittedValue)==false)
                    InputControl.log.debug("Replacing submitted value from '{}' to '{}' for " + clientId, oldValue, submittedValue);
            }
            reqMap.put(clientId, submittedValue);
        }
        // Convert
        if ((submittedValue instanceof String) && ((String) submittedValue).length() > 0)
        {   // debug
            if (log.isDebugEnabled())
                log.debug("Converting value for colum {}. Value is {}", ii.getColumn().getName(), submittedValue);
            // parse
            return parseInputValue((String) submittedValue, ii);
        }            
        return submittedValue;
    }
    
    /**
     * adds style attributes related to the current value
     * @param vi
     * @param value the current value
     * @param styleClass
     * @return
     */
    protected String addDataValueStyle(ValueInfo vi, Object value, String styleClass)
    {
        DataType dataType = vi.getColumn().getDataType();
        if (ObjectUtils.isEmpty(value))
        {   // Null
            styleClass += " eValNull";
        }
        else if (dataType.isNumeric())
        {   // Check negative
            if (ObjectUtils.getLong(value)<0)
                styleClass += " eValNeg";
        }
        return styleClass;
    }

    protected void addAttachedObjects(UIComponent parent, FacesContext context, InputInfo ii, UIComponentBase inputComponent)
    {
        InputAttachedObjectsHandler aoh = InputControlManager.getAttachedObjectsHandler();
        if (aoh!=null)
            aoh.addAttachedObjects(parent, context, ii.getColumn(), inputComponent);
    }
    
    protected void updateAttachedObjects(UIComponent parent, FacesContext context, InputInfo ii, UIComponentBase inputComponent)
    {
        InputAttachedObjectsHandler aoh = InputControlManager.getAttachedObjectsHandler();
        if (aoh!=null)
            aoh.updateAttachedObjects(parent, context, ii.getColumn(), inputComponent);
    }
    
    protected UIInput getFirstInput(List<UIComponent> compList)
    {
        for (int i=0; i<compList.size(); i++)
        {
            UIComponent child = compList.get(i);
            if (child instanceof UIInput)
                return ((UIInput)child);
        }
        throw new ItemNotFoundException("UIInput");
    }
    
    protected void setInputValue(UIInput input, InputInfo ii)
    {
        // Restore submitted value
        FacesContext fc = FacesContext.getCurrentInstance();
        Map<String, Object> reqMap = fc.getExternalContext().getRequestMap();
        String clientId = input.getClientId();
        if (reqMap.containsKey(clientId))
        { // Set the local value from the request map
            Object value = reqMap.get(clientId);
            if (input.isLocalValueSet() == false)
                input.setSubmittedValue(value);
            // change the style
            addRemoveValueNullStyle(input, ObjectUtils.isEmpty(value));
            return;
        }
        else if (input.getSubmittedValue() != null) //  && FacesUtils.isClearSubmittedValues(fc)
        { // Clear submitted value   
            if (InputControl.log.isDebugEnabled())
                InputControl.log.debug("clearing submitted value for {}. value is {}.", ii.getColumn().getName(), input.getSubmittedValue());
            input.setSubmittedValue(null);
        }

        /* -------------------------------------- */

        // Assign value
        Object value = ii.getValue(false);
        if (value instanceof ValueExpression)
        {
            input.setValue(null);
            input.setLocalValueSet(false);
            input.setValueExpression("value", (ValueExpression) value);

            // Object check = ((ValueExpression)value).getValue(FacesContext.getCurrentInstance().getELContext());
            // log.info("Expression value is {}.", check);
        }
        else
        { // Set the value
            value = formatInputValue(value, ii);
            input.setValue(value);
            // change the style
            addRemoveValueNullStyle(input, ObjectUtils.isEmpty(value));
        }
    }

    protected void clearSubmittedValue(UIInput input)
    {
        input.setSubmittedValue(null);
        // check Request Map
        FacesContext fc = FacesContext.getCurrentInstance();
        Map<String, Object> reqMap = fc.getExternalContext().getRequestMap();
        String clientId = input.getClientId();
        if (reqMap.containsKey(clientId))
            reqMap.remove(clientId);
    }

    /**
     * Override this to format a value for output
     * 
     * @param value
     * @param ii
     * @return
     */
    protected Object formatInputValue(Object value, InputInfo ii)
    {
        return value;
    }

    protected Object parseInputValue(String value, InputInfo ii)
    {
        return value;
    }

    /* validate 
    public boolean validateValue(UIComponent comp, InputInfo ii, FacesContext context)
    {
        UIInput input = getInputComponent(comp);
        if (input==null)
            throw new ObjectNotValidException(this);
        
        input.validate(context);
        if (input.isValid()==false)
            return false;
        /-*
        Object value = getInputValue(comp, ii, context, false);
        try {
            ii.getColumn().validate(value);
            Object xxx = input.getLocalValue();
            // Wert geändert?
            Object previous = ii.getValue();
            if (ObjectUtils.compareEqual(value, previous)==false)
            {
                comp.queueEvent(new ValueChangeEvent(comp, previous, value));
                // Wert setzen
                ii.setValue(value, true);
            }
            return true;
            
        } catch(Exception e) {
            // Add Error Messgae
            String text = e.getLocalizedMessage();
            FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, text, text);
            context.addMessage(comp.getClientId(), msg);
            // Invalid
            ii.setValue(value, false);
            return false;
        }
        *-/
        return true;
    }
    */

    /* Input helpers */
    protected abstract void createInputComponents(UIComponent parent, InputInfo ii, FacesContext context, List<UIComponent> compList);

    protected abstract void updateInputState(List<UIComponent> compList, InputInfo ii, FacesContext context, PhaseId phaseId);
    
    protected UIInput getInputComponent(UIComponent parent)
    {
        // default implementation
        int count = parent.getChildCount();
        if (count < 1)
            return null;
        // find the UIInput component (only one allowed here)
        UIInput inp = null;
        for (int i = 0; i < count; i++)
        { // check UIInput 
            UIComponent comp = parent.getChildren().get(i);
            if (comp instanceof UIInput)
            {   if (inp != null)
                    throw new UnexpectedReturnValueException(comp, "comp.getChildren().get(" + String.valueOf(i) + ")");
                inp = (UIInput) comp;
            }
        }
        // No UIInput found
        if (inp == null)
        {   // Check whether inside a DataTable (javax.faces.component.UIData)
            for (UIComponent p = parent.getParent(); p!=null; p=p.getParent())
            {   // Check whether inside UIData
                if (p instanceof UIData) {
                    log.info("Ignore value component for id '{}' inside a DataTable (javax.faces.component.UIData)", parent.getClientId());
                    return null;
                }
            }
            // Should not happen!
            throw new UnexpectedReturnValueException(null, "comp.getChildren().get()");
        }
        // found one
        return inp;
    }

    protected String getInputStyleClass(InputInfo ii, String additonalStyle)
    {
        return ii.getStyleClass(additonalStyle);
    }

    protected void setInputStyleClass(UIInput input, String cssStyleClass)
    {
        input.getAttributes().put("styleClass", cssStyleClass);
    }

    protected void copyAttributes(UIComponent parent, InputInfo ii, UIInput input, String additonalStyle)
    {
        String inputId = ii.getInputId();
        if (StringUtils.isNotEmpty(inputId))
        {
            input.getAttributes().put("id", inputId);
        }

        // set style class
        String styleClass = getInputStyleClass(ii, additonalStyle);
        setInputStyleClass(input, styleClass);

        // copy standard attributes
        copyAttribute(ii, input, "style");
        copyAttribute(ii, input, "tabindex");
        copyAttribute(ii, input, "onchange");
        copyAttribute(ii, input, "onfocus");
        copyAttribute(ii, input, "onblur");
        copyAttribute(ii, input, "onkeydown");
        copyAttribute(ii, input, "onkeyup");
        copyAttribute(ii, input, "onclick");

        // immediate
        Object immediate = ii.getAttribute("immediate");
        if (immediate != null && ObjectUtils.getBoolean(immediate))
        {
            InputControl.log.warn("Immediate attribute is not yet supported for {}!", ii.getColumn().getName());
            // input.setImmediate(true);
        }

        // validator
        // input.addValidator(new ColumnValueValidator(ii.getColumn()));
    }

    protected final void copyAttributes(UIComponent parent, InputInfo ii, UIInput input)
    {
        copyAttributes(parent, ii, input, (ii.isRequired() ? STYLECLASS_REQUIRED : null));
    }

    protected void copyAttribute(InputInfo ii, UIInput input, String name)
    {
        if (ii == null)
            throw new InvalidArgumentException("InputInfo", ii);
        // get Attribute
        Object value = ii.getAttribute(name);
        if (value == null)
            value = ii.getColumn().getAttribute(name);
        if (value != null)
            input.getAttributes().put(name, String.valueOf(value));
    }
    
    public void addRemoveValueNullStyle(UIInput input, boolean nullValue)
    {
        addRemoveStyle(input, " eValNull", nullValue);
    }

    public void addRemoveDisabledStyle(UIInput input, boolean disabled)
    {
        addRemoveStyle(input, " eInpDis", disabled);
    }

    public void addRemoveInvalidStyle(UIInput input, boolean invalid)
    {
        addRemoveStyle(input, " eInvalid", invalid);
    }

    public void addRemoveStyle(UIInput input, String styleName, boolean setStyle)
    {
        String styleClass = StringUtils.toString(input.getAttributes().get("styleClass"), "");
        boolean hasStyle = (styleClass.indexOf(styleName) >= 0);
        if (setStyle == hasStyle)
            return; // Nothing to do
        // Special IceFaces patch
        if (styleClass.endsWith("-dis"))
            styleClass = styleClass.substring(0, styleClass.length() - 4);
        // add or remove disabled style
        if (setStyle)
            styleClass += styleName;
        else
            styleClass = styleClass.replace(styleName, "");
        // add Style
        setInputStyleClass(input, styleClass);
    }
    
    /**
     * Returns the value formated as a string
     * this is a simple default implementation that does no type-secific formatting
     * Derived classes may override formatString an provide further formmatting
     * see TextInputControl for details
     * 
     * @param value
     *            the value to be formatted
     * @param vi
     *            Meta-information about the value
     * @return the formatted value
     */
    protected String formatValue(Object value, ValueInfo vi)
    {
        // For Enums use toString() to retrieve Value
        if (value != null && value.getClass().isEnum() && !hasFormatOption(vi, "nolookup"))
        { // Handle enum
            String text = ((Enum<?>) value).toString();
            if (text != null)
                return vi.getText(text);
            // Error
            InputControl.log.error("The enum '" + ((Enum<?>) value).name() + "' has no text!");
        }
        // Lookup and Print value
        Options options = vi.getOptions();
        if (options != null && !options.isEmpty() && !hasFormatOption(vi, "nolookup"))
        {   // Check for Options
            OptionEntry entry = options.getEntry(value);
            if (entry!=null)
                return vi.getText(entry.getText());
            // Error
            if (value!=null)
                InputControl.log.error("The element '" + String.valueOf(value) + "' is not part of the supplied option list.");
        }
        // value
        if (value == null)
            value = getFormatOption(vi, InputControl.FORMAT_NULL, InputControl.FORMAT_NULL_ATTRIBUTE);
        // Convert to String
        String s = StringUtils.toString(value, "");
        if (hasFormatOption(vi, "noencode"))
            return s;
        // Encode Html
        return escapeHTML(s);
    }

    /**
     * Returns the value formated as a string
     * This is a shortcut for formatString(vi.getValue(), vi)
     * Derived classes may override formatString
     */
    protected final String formatValue(ValueInfo vi)
    {
        // boolean hasError = ((vi instanceof InputInfo) && !((InputInfo)vi).isValid()); 
        return formatValue(vi.getValue(true), vi);
    }

    /**
     * escapes a String for html
     * 
     * @param text
     * @return the escaped html String
     */
    protected String escapeHTML(String text)
    {
        if (text==null || text.length()==0)
            return text;
        // &amp;
        if (text.indexOf('&')>=0)
            text = StringUtils.replaceAll(text, "&", "&amp;");
        // &lt;
        if (text.indexOf('<')>=0)
            text = StringUtils.replaceAll(text, "<", "&lt;");
        // &gt;
        if (text.indexOf('>')>=0)
            text = StringUtils.replaceAll(text, ">", "&gt;");
        // done
        return text;
    }

    /**
     * checks if a particular formating option has been specified.
     * 
     * @param vi
     *            the value info
     * @param option
     *            the formating option to check
     * @return true if the requested formating option has been specified or false otherwise
     */
    protected boolean hasFormatOption(ValueInfo vi, String option)
    {
        String format = vi.getFormat();
        return (format != null ? format.indexOf(option) >= 0 : false);
    }

    protected boolean hasFormatOption(ValueInfo vi, String option, String columnAttributeName)
    {
        if (hasFormatOption(vi, option))
            return true;
        // column format provided?
        Column column = vi.getColumn();
        return (column!=null ? !ObjectUtils.isEmpty(column.getAttribute(columnAttributeName)) : false);
    }
    
    protected String getFormatOption(ValueInfo vi, String option)
    {
        // Is unit supplied with format
        String format = vi.getFormat();
        if (format == null)
            return null;
        // Check for option
        int beg = format.indexOf(option);
        if (beg < 0)
            return null;
        // Find
        beg = beg + option.length();
        int end = format.indexOf(';', beg + 1);
        if (end < beg)
            return format.substring(beg);
        // The cbValue
        return format.substring(beg, end);
    }

    protected Object getFormatOption(ValueInfo vi, String option, String columnAttributeName)
    {
        // direct format provided?
        String format = getFormatOption(vi, option);
        if (format!=null)
            return format;
        // column format provided?
        Column column = vi.getColumn();
        return (column!=null ? column.getAttribute(columnAttributeName) : null);
    }

    protected String getFormatString(ValueInfo vi, String option, String columnAttributeName)
    {
        return StringUtils.toString(getFormatOption(vi, option, columnAttributeName));
    }

    protected int getFormatInteger(ValueInfo vi, String option, String columnAttributeName)
    {
        return ObjectUtils.getInteger(getFormatOption(vi, option, columnAttributeName));
    }

}
