/*
 * 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.click.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import ognl.DefaultTypeConverter;
import ognl.Ognl;
import ognl.OgnlOps;

import org.apache.click.Control;
import org.apache.click.Page;
import org.apache.click.control.Button;
import org.apache.click.control.Container;
import org.apache.click.control.Field;
import org.apache.click.control.FieldSet;
import org.apache.click.control.Form;
import org.apache.click.control.Label;
import org.apache.click.service.LogService;
import org.apache.commons.lang.ClassUtils;

/**
 * Provides Container access and copy utilities.
 */
public class ContainerUtils {

    /**
     * Populate the given object attributes from the Containers field values.
     * <p/>
     * If a Field and object attribute matches, the object attribute is set to
     * the Object returned from the method
     * {@link org.apache.click.control.Field#getValueObject()}. If an object
     * attribute is a primitive, the Object returned from
     * {@link org.apache.click.control.Field#getValueObject()} will be converted
     * into the specific primitive e.g. Integer will become int and Boolean will
     * become boolean.
     * <p/>
     * The fieldList specifies which fields to copy to the object. This allows
     * one to include or exclude certain Container fields before populating the
     * object.
     * <p/>
     * The following example shows how to exclude disabled fields from
     * populating a customer object:
     * <pre class="prettyprint">
     * public void onInit() {
     *     List formFields = new ArrayList();
     *     for(Iterator it = form.getFieldList().iterator(); it.hasNext(); ) {
     *         Field field = (Field) formFields.next();
     *         // Exclude disabled fields
     *         if (!field.isDisabled()) {
     *             formFields.add(field);
     *         }
     *     }
     *     Customer customer = new Customer();
     *     ContainerUtils.copyContainerToObject(form, customer, formFields);
     * }
     * </pre>
     *
     * The specified Object can either be a POJO (plain old java object) or
     * a {@link java.util.Map}. If a POJO is specified, its attributes are
     * populated from  matching container fields. If a map is specified, its
     * key/value pairs are populated from matching container fields.
     *
     * @param container the fieldList Container
     * @param object the object to populate with field values
     * @param fieldList the list of fields to obtain values from
     *
     * @throws IllegalArgumentException if container, object or fieldList is
     * null
     */
    public static void copyContainerToObject(Container container,
        Object object, List<Field> fieldList) {

        if (container == null) {
            throw new IllegalArgumentException("Null container parameter");
        }

        if (object == null) {
            throw new IllegalArgumentException("Null object parameter");
        }

        if (fieldList == null) {
            throw new IllegalArgumentException("Null fieldList parameter");
        }

         if (fieldList.isEmpty()) {
            LogService logService = ClickUtils.getLogService();
            if (logService.isDebugEnabled()) {
                String containerClassName =
                    ClassUtils.getShortClassName(container.getClass());
                logService.debug("   " + containerClassName
                                 + " has no fields to copy from");
            }
            //Exit early.
            return;
        }

        String objectClassname = object.getClass().getName();
        objectClassname =
            objectClassname.substring(objectClassname.lastIndexOf(".") + 1);

        // If the given object is a map, its key/value pair is populated from
        // the fields name/value pair.
        if (object instanceof Map<?, ?>) {
            copyFieldsToMap(fieldList, (Map) object);
            // Exit after populating the map.
            return;
        }

        LogService logService = ClickUtils.getLogService();

        Set<String> properties = getObjectPropertyNames(object);
        Map<?, ?> ognlContext = Ognl.createDefaultContext(
                object, null, new FixBigDecimalTypeConverter(), null);

        for (Field field : fieldList) {

            // Ignore disabled field as their values are not submitted in HTML
            // forms
            if (field.isDisabled()) {
                continue;
            }

            if (!hasMatchingProperty(field, properties)) {
                continue;
            }

            String fieldName = field.getName();

            ensureObjectPathNotNull(object, fieldName);

            try {
                PropertyUtils.setValueOgnl(object, fieldName, field.getValueObject(), ognlContext);

                if (logService.isDebugEnabled()) {
                    String containerClassName =
                        ClassUtils.getShortClassName(container.getClass());
                    String msg = "    " + containerClassName + " -> "
                        + objectClassname + "." + fieldName + " : "
                        + field.getValueObject();

                    logService.debug(msg);
                }

            } catch (Exception e) {
                String msg =
                    "Error incurred invoking " + objectClassname + "."
                    + fieldName + " with " + field.getValueObject()
                    + " error: " + e.toString();

                logService.debug(msg);
            }
        }
    }
    
    /**
     * Populate the given object attributes from the Containers field values.
     *
     * @see #copyContainerToObject(org.apache.click.control.Container, java.lang.Object, java.util.List)
     *
     * @param container the Container to obtain field values from
     * @param object the object to populate with field values
     */
    public static void copyContainerToObject(Container container,
        Object object) {
        List<Field> fieldList = getInputFields(container);
        copyContainerToObject(container, object, fieldList);
    }

    /**
     * Populate the given Container field values from the object attributes.
     * <p/>
     * If a Field and object attribute matches, the Field value is set to the
     * object attribute using the method
     * {@link org.apache.click.control.Field#setValueObject(java.lang.Object)}. If
     * an object attribute is a primitive it is first converted to its proper
     * wrapper class e.g. int will become Integer and boolean will become
     * Boolean.
     * <p/>
     * The fieldList specifies which fields to populate from the object. This
     * allows one to exclude or include specific fields.
     * <p/>
     * The specified Object can either be a POJO (plain old java object) or
     * a {@link java.util.Map}. If a POJO is specified, its attributes are
     * copied to matching container fields. If a map is specified, its key/value
     * pairs are copied to matching container fields.
     *
     * @param object the object to obtain attribute values from
     * @param container the Container to populate
     * @param fieldList the list of fields to populate from the object
     * attributes
     */
    public static void copyObjectToContainer(Object object,
        Container container, List<Field> fieldList) {
        if (object == null) {
            throw new IllegalArgumentException("Null object parameter");
        }

        if (container == null) {
            throw new IllegalArgumentException("Null container parameter");
        }

        if (container == null) {
            throw new IllegalArgumentException("Null fieldList parameter");
        }

        if (fieldList.isEmpty()) {
            LogService logService = ClickUtils.getLogService();
            if (logService.isDebugEnabled()) {
                String containerClassName =
                    ClassUtils.getShortClassName(container.getClass());
                logService.debug("   " + containerClassName
                    + " has no fields to copy to");
            }
            //Exit early.
            return;
        }

        String objectClassname = object.getClass().getName();
        objectClassname =
            objectClassname.substring(objectClassname.lastIndexOf(".") + 1);

        //If the given object is a map, populate the fields name/value from
        //the maps key/value pair.
        if (object instanceof Map<?, ?>) {

            copyMapToFields((Map) object, fieldList);
            //Exit after populating the fields.
            return;
        }

        Set<String> properties = getObjectPropertyNames(object);

        LogService logService = ClickUtils.getLogService();

        for (Field field : fieldList) {

            if (!hasMatchingProperty(field, properties)) {
                continue;
            }

            String fieldName = field.getName();
            try {
                Object result = PropertyUtils.getValue(object, fieldName);

                field.setValueObject(result);

                if (logService.isDebugEnabled()) {
                    String containerClassName =
                        ClassUtils.getShortClassName(container.getClass());
                    String msg = "    " + containerClassName + " <- "
                        + objectClassname + "." + fieldName + " : "
                        + result;
                    logService.debug(msg);
                }

            } catch (Exception e) {
                String msg = "Error incurred invoking " + objectClassname + "."
                    + fieldName + " error: " + e.toString();

                logService.debug(msg);
            }
        }
    }

    /**
     * Populate the given Container field values from the object attributes.
     *
     * @see #copyObjectToContainer(java.lang.Object, org.apache.click.control.Container, java.util.List)
     *
     * @param object the object to obtain attribute values from
     * @param container the Container to populate
     */
    public static void copyObjectToContainer(Object object,
        Container container) {

        List<Field> fieldList = getInputFields(container);
        copyObjectToContainer(object, container, fieldList);
    }

    /**
     * Find and return the first control with a matching name in the specified
     * container.
     * <p/>
     * If no matching control is found in the specified container, child
     * containers will be recursively scanned for a match.
     *
     * @param container the container that is searched for a control with a
     * matching name
     * @param name the name of the control to find
     * @return the control which name matched the given name
     */
    public static Control findControlByName(Container container, String name) {
        Control control = container.getControl(name);

        if (control != null) {
            return control;

        } else {
            for (Control childControl : container.getControls()) {

                if (childControl instanceof Container) {
                    Container childContainer = (Container) childControl;
                    Control found = findControlByName(childContainer, name);
                    if (found != null) {
                        return found;
                    }
                }
            }
        }
        return null;
    }

    /**
     * Find and return the specified controls parent Form or null
     * if no Form is present.
     *
     * @param control the control to check for Form
     * @return the controls parent Form or null if no parent is a Form
     */
    public static Form findForm(Control control) {
        while (control.getParent() != null && !(control.getParent() instanceof Page)) {
            control = (Control) control.getParent();
            if (control instanceof Form) {
                return (Form) control;
            }
        }
        return null;
    }

    /**
     * Return the list of Buttons for the given Container, recursively including
     * any Fields contained in child containers.
     *
     * @param container the container to obtain the buttons from
     * @return the list of contained buttons
     */
    public static List<Button> getButtons(Container container) {
        if (container == null) {
            throw new IllegalArgumentException("Null container parameter");
        }

        List<Button> buttons = new ArrayList<Button>();
        addButtons(container, buttons);
        return buttons;
    }

    /**
     * Return a list of container fields which are not valid, not hidden and not
     * disabled.
     * <p/>
     * The list of returned fields will exclude any <tt>Button</tt> fields.
     *
     * @param container the container to obtain the invalid fields from
     * @return list of container fields which are not valid, not hidden and not
     * disabled
     */
    public static List<Field> getErrorFields(Container container) {
        if (container == null) {
            throw new IllegalArgumentException("Null container parameter");
        }

        List<Field> fields = new ArrayList<Field>();
        addErrorFields(container, fields);
        return fields;
    }

    /**
     * Return a map of all Fields for the given Container, recursively including
     * any Fields contained in child containers.
     * <p/>
     * The map's key / value pair will consist of the control name and instance.
     *
     * @param container the container to obtain the fields from
     * @return the map of contained fields
     */
    public static Map<String, Field> getFieldMap(Container container) {
        if (container == null) {
            throw new IllegalArgumentException("Null container parameter");
        }

        Map<String, Field> fields = new HashMap<String, Field>();
        addFields(container, fields);
        return fields;
    }

    /**
     * Return the list of Fields for the given Container, recursively including
     * any Fields contained in child containers.
     *
     * @param container the container to obtain the fields from
     * @return the list of contained fields
     */
    public static List<Field> getFields(Container container) {
        if (container == null) {
            throw new IllegalArgumentException("Null container parameter");
        }

        List<Field> fields = new ArrayList<Field>();
        addFields(container, fields);
        return fields;
    }

    /**
     * Return the list of Fields for the given Container, recursively including
     * any Fields contained in child containers. The list of returned fields
     * will exclude any <tt>Button</tt> and <tt>FieldSet</tt> fields.
     *
     * @param container the container to obtain the fields from
     * @return the list of contained fields
     */
    public static List<Field> getFieldsAndLabels(Container container) {
        if (container == null) {
            throw new IllegalArgumentException("Null container parameter");
        }

        List<Field> fields = new ArrayList<Field>();
        addFieldsAndLabels(container, fields);
        return fields;
    }

    /**
     * Return the list of hidden Fields for the given Container, recursively including
     * any Fields contained in child containers. The list of returned fields
     * will exclude any <tt>Button</tt>, <tt>FieldSet</tt> and <tt>Label</tt>
     * fields.
     *
     * @param container the container to obtain the fields from
     * @return the list of contained fields
     */
    public static List<Field> getHiddenFields(final Container container) {
        if (container == null) {
            throw new IllegalArgumentException("Null container parameter");
        }

        List<Field> fields = new ArrayList<Field>();
        addHiddenFields(container, fields);
        return fields;
    }

    /**
     * Return the list of input Fields (TextField, Select, Radio, Checkbox etc).
     * for the given Container, recursively including any Fields contained in
     * child containers. The list of returned fields will exclude any
     * <tt>Button</tt>, <tt>FieldSet</tt> and <tt>Label</tt> fields.
     *
     * @param container the container to obtain the fields from
     * @return the list of contained fields
     */
    public static List<Field> getInputFields(final Container container) {
        if (container == null) {
            throw new IllegalArgumentException("Null container parameter");
        }

        List<Field> fields = new ArrayList<Field>();
        addInputFields(container, fields);
        return fields;
    }

    /**
     * Add the given control to the container at the specified index, and return
     * the added instance.
     * <p/>
     * <b>Please note</b>: an exception is raised if the container contains a
     * control with the same name as the given control. It is the responsibility
     * of the caller to replace existing controls.
     * <p/>
     * <b>Also note</b> if the specified control already has a parent assigned,
     * it will automatically be removed from that parent and inserted as a child
     * of the container instead.
     * <p/>
     * This method is useful for developers needing to implement the
     * {@link org.apache.click.control.Container} interface but cannot for one
     * reason or another extend from {@link org.apache.click.control.AbstractContainer}.
     * For example if the Container already extends from an existing <tt>Control</tt>
     * such as a <tt>Field</tt>, it won't be possible to extend
     * <tt>AbstractContainer</tt> as well. In such scenarios instead of
     * reimplementing {@link org.apache.click.control.Container#insert(org.apache.click.Control, int) insert},
     * one can delegate to this method.
     * <p/>
     * For example, a custom Container that extends <tt>Field</tt> and
     * implements <tt>Container</tt> could implement the <tt>insert</tt> method
     * as follows:
     * <pre class="prettyprint">
     * public class MyContainer extends Field implements Container {
     *
     *     public Control insert(Control control, int index) {
     *         return ContainerUtils.insert(this, control, index, getControlMap());
     *     }
     *
     *     ...
     * } </pre>
     *
     * @param container the container to insert the given control into
     * @param control the control to add to the container
     * @param index the index at which the control is to be inserted
     * @param controlMap the container's map of controls keyed on control name
     * @return the control that was added to the container
     *
     * @throws IllegalArgumentException if the control is null or if the control
     * and container is the same instance
     *
     * @throws IndexOutOfBoundsException if index is out of range
     * <tt>(index &lt; 0 || index &gt; container.getControls().size())</tt>
     */
    public static Control insert(Container container, Control control, int index,
        Map<String, Control> controlMap) {

        // Pre conditions start
        if (control == null) {
            throw new IllegalArgumentException("Null control parameter");
        }
        if (control == container) {
            throw new IllegalArgumentException("Cannot add container to itself");
        }
        int size = container.getControls().size();
        if (index > size || index < 0) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
                + size);
        }
        // Check if container already contains the control
        if (controlMap.containsKey(control.getName())
            && !(control instanceof Label)) {

            throw new IllegalArgumentException(
                "Container already contains control named: " + control.getName());
        }

        // Pre conditions end

        // Check if control already has parent
        // If parent references the given container, there is no need to remove it
        Object currentParent = control.getParent();
        if (currentParent != null && currentParent != container) {

            // Remove control from parent Page or Container
            if (currentParent instanceof Page) {
                ((Page) currentParent).removeControl(control);

            } else if (currentParent instanceof Container) {
                ((Container) currentParent).remove(control);
            }

            // Create warning message to users that the parent has been reset
            logParentReset(container, control, currentParent);
        }

        // Note: set parent first since setParent might veto further processing
        control.setParent(container);
        container.getControls().add(index, control);

        String controlName = control.getName();
        if (controlName != null) {
            controlMap.put(controlName, control);
        }
        return control;
    }

    /**
     * Replace the current control in the container at the specified index, and
     * return the newly added control.
     * <p/>
     * <b>Please note</b> if the new control already has a parent assigned,
     * it will automatically be removed from that parent and inserted as a child
     * of the container instead.
     * <p/>
     * This method is useful for developers needing to implement the
     * {@link org.apache.click.control.Container} interface but cannot for one
     * reason or another extend from {@link org.apache.click.control.AbstractContainer}.
     * For example if the Container already extends from an existing <tt>Control</tt>
     * such as a <tt>Field</tt>, it won't be possible to extend
     * <tt>AbstractContainer</tt> as well. In such scenarios instead of
     * reimplementing {@link org.apache.click.control.Container#replace(org.apache.click.Control, org.apache.click.Control) replace},
     * one can delegate to this method.
     * <p/>
     * For example, a custom Container that extends <tt>Field</tt> and
     * implements <tt>Container</tt> could implement the <tt>replace</tt> method
     * as follows:
     *
     * <pre class="prettyprint">
     * public class MyContainer extends Field implements Container {
     *
     *     public Control replace(Control currentControl, Control newControl) {
     *         int controlIndex = getControls().indexOf(currentControl);
     *         return ContainerUtils.replace(this, currentControl, newControl,
     *             controlIndex, getControlMap());
     *     }
     *
     *     ...
     * } </pre>
     *
     * @param container the container to insert the new control into
     * @param currentControl the control currently contained in the container
     * @param newControl the control to replace the current control contained in
     * the container
     * @param controlIndex the index of the current control in the container
     * @param controlMap the container's map of controls keyed on control name
     * @return the new control that replaced the current control
     *
     * @deprecated this method was used for stateful pages, which have been deprecated
     *
     * @throws IllegalArgumentException if the currentControl or newControl is
     * null
     * @throws IllegalStateException if the controlIndex = -1
     */
    public static Control replace(Container container, Control currentControl,
        Control newControl, int controlIndex, Map<String, Control> controlMap) {

        // Pre conditions start

        // Current and new control is the same instance - exit early
        if (currentControl == newControl) {
            return newControl;
        }

        if (currentControl == null) {
            throw new IllegalArgumentException("Null current control parameter");
        }
        if (newControl == null) {
            throw new IllegalArgumentException("Null new control parameter");
        }

        if (controlIndex == -1) {
            throw new IllegalStateException("Cannot replace the given control"
                + " because it is not present in the container");
        }

        // Pre conditions end

        // Check if control already has parent
        // If parent references the given container, there is no need to remove it
        Object currentParent = newControl.getParent();
        if (currentParent != null && currentParent != container) {

            // Remove new control from parent Page or Container
            if (currentParent instanceof Page) {
                ((Page) currentParent).removeControl(newControl);

            } else if (currentParent instanceof Container) {
                ((Container) currentParent).remove(newControl);
            }

            // Create warning message to users that the parent has been reset
            logParentReset(container, newControl, currentParent);
        }

        // Note: set parent first since setParent might veto further processing
        newControl.setParent(container);
        currentControl.setParent(null);

        // Replace currentControl with newControl
        container.getControls().set(controlIndex, newControl);

        // Update controlMap
        String controlName = newControl.getName();
        if (controlName != null) {
            controlMap.put(controlName, newControl);
        } else {
            controlName = currentControl.getName();

            if (controlName != null) {
                controlMap.remove(controlName);
            }
        }
        return newControl;
    }

    /**
     * Remove the given control from the container, returning <tt>true</tt> if
     * the control was found in the container and removed, or <tt>false</tt> if
     * the control was not found.
     * <p/>
     * This method is useful for developers needing to implement the
     * {@link org.apache.click.control.Container} interface but cannot for one
     * reason or another extend from {@link org.apache.click.control.AbstractContainer}.
     * For example if the Container already extends from an existing <tt>Control</tt>
     * such as a <tt>Field</tt>, it won't be possible to extend
     * <tt>AbstractContainer</tt> as well. In such scenarios instead of
     * reimplementing {@link org.apache.click.control.Container#remove(org.apache.click.Control) remove},
     * one can delegate to this method.
     * <p/>
     * For example, a custom Container that extends <tt>Field</tt> and
     * implements <tt>Container</tt> could implement the <tt>remove</tt> method
     * as follows:
     * <pre class="prettyprint">
     * public class MyContainer extends Field implements Container {
     *
     *     public boolean remove (Control control) {
     *         return ContainerUtils.remove(this, control, getControlMap());
     *     }
     *
     *     ...
     * } </pre>
     *
     * @param container the container to remove the given control from
     * @param control the control to remove from the container
     * @param controlMap the container's map of controls keyed on control name
     *
     * @return true if the control was removed from the container
     * @throws IllegalArgumentException if the control is null
     */
    public static boolean remove(Container container, Control control,
        Map<String, Control> controlMap) {

        if (control == null) {
            throw new IllegalArgumentException("Control cannot be null");
        }

        boolean contains = container.getControls().remove(control);

        if (contains) {
            // Only nullify if the container is parent. This check is for the
            // case where a Control has two parents e.g. Page and Form.
            // NOTE the current #insert logic does not allow Controls to have
            // two parents so this check might be redundant.
            if (control.getParent() == container) {
                control.setParent(null);
            }

            String controlName = control.getName();

            if (controlName != null) {
                controlMap.remove(controlName);
            }
        }

        return contains;
    }

    // -------------------------------------------------------- Private Methods

    /**
     * Extract and return the specified object property names.
     * <p/>
     * If the object is a Map instance, this method returns the maps key set.
     *
     * @param object the object to extract property names from
     * @return the unique set of property names
     */
    private static Set<String> getObjectPropertyNames(Object object) {
        if (object instanceof Map) {
            return ((Map) object).keySet();
        }

        Set<String> hashSet = new TreeSet<String>();

        Method[] methods = object.getClass().getMethods();

        for (Method method : methods) {
            String methodName = method.getName();

            if (methodName.startsWith("get") && methodName.length() > 3) {
                String propertyName =
                    Character.toLowerCase(methodName.charAt(3))
                    + methodName.substring(4);
                hashSet.add(propertyName);
            }
            if (methodName.startsWith("is") && methodName.length() > 2) {
                String propertyName =
                    Character.toLowerCase(methodName.charAt(2))
                    + methodName.substring(3);
                hashSet.add(propertyName);
            }
            if (methodName.startsWith("set") && methodName.length() > 3) {
                String propertyName =
                    Character.toLowerCase(methodName.charAt(3))
                    + methodName.substring(4);
                hashSet.add(propertyName);
            }
        }

        return hashSet;
    }

    /**
     * Return true if the specified field name is contained within the
     * specified set of properties.
     *
     * @param field the field which name should be checked
     * @param properties set of properties to check
     * @return true if the specified field name is contained in the properties,
     * false otherwise
     */
    private static boolean hasMatchingProperty(Field field, Set<String> properties) {
        String fieldName = field.getName();
        if (fieldName.indexOf(".") != -1) {
            fieldName = fieldName.substring(0, fieldName.indexOf("."));
        }
        return properties.contains(fieldName);
    }

    /**
     * This method ensures that the object can safely be navigated according
     * to the specified path.
     * <p/>
     * If any object in the graph is null, a new instance of that object class
     * is instantiated.
     *
     * @param object the object which path must be navigable without
     * encountering null values
     * @param path the navigation path
     */
    private static void ensureObjectPathNotNull(Object object, String path) {

        final int index = path.indexOf('.');

        if (index == -1) {
            return;
        }

        String property = path.substring(0, index);
        Method getterMethod = findGetter(object, property, path);
        Object result = invokeGetter(getterMethod, object, property, path);

        if (result == null) {
            // Find the target class of the object in the path to create
            Class<?> targetClass = getterMethod.getReturnType();

            Constructor<?> constructor = null;
            try {
                // Lookup default no-arg constructor
                constructor = targetClass.getConstructor((Class[]) null);

            } catch (NoSuchMethodException e) {
                // Log detailed error message of looking up constructor failed
                HtmlStringBuffer buffer = new HtmlStringBuffer();
                logBasicDescription(buffer, object, path, property);
                buffer.append("Attempt to construct instance of class '");
                buffer.append(targetClass.getName()).append("' resulted in error: '");
                buffer.append(targetClass.getName()).append("' does not seem");
                buffer.append(" to have a default no argument constructor.");
                buffer.append(" Please note another common problem is that the");
                buffer.append(" class is either not public or not static.");
                throw new RuntimeException(buffer.toString(), e);
            }

            try {
                // Create target object instance
                result = constructor.newInstance(new Object[]{});

            } catch (Exception e) {
                // Log detailed error message of why creating target failed
                HtmlStringBuffer buffer = new HtmlStringBuffer();
                logBasicDescription(buffer, object, path, property);
                buffer.append("Result: could not create");
                buffer.append(" object with constructor '");
                buffer.append(constructor.getName()).append("'.");
                throw new RuntimeException(buffer.toString(), e);
            }

            Method setterMethod = findSetter(object, property, targetClass, path);
            invokeSetter(setterMethod, object, result, property, path);
        }

        String remainingPath = path.substring(index + 1);

        ensureObjectPathNotNull(result, remainingPath);
    }

    /**
     * Find the object getter method for the given property.
     * <p/>
     * If this method cannot find a 'get' property it tries to lookup an 'is'
     * property.
     *
     * @param object the object to find the getter method on
     * @param property the getter property name specifying the getter to lookup
     * @param path the full expression path (used for logging purposes)
     * @return the getter method
     */
    private static Method findGetter(Object object, String property,
        String path) {

        // Find the getter for property
        String getterName = ClickUtils.toGetterName(property);

        Method method = null;
        Class<?> sourceClass = object.getClass();

        try {
            method = sourceClass.getMethod(getterName, (Class[]) null);
        } catch (Exception e) {
        }

        if (method == null) {
            String isGetterName = ClickUtils.toIsGetterName(property);
            try {
                method = sourceClass.getMethod(isGetterName, (Class[]) null);
            } catch (Exception e) {
                HtmlStringBuffer buffer = new HtmlStringBuffer();
                logBasicDescription(buffer, object, path, property);
                buffer.append("Result: neither getter methods '");
                buffer.append(getterName).append("()' nor '");
                buffer.append(isGetterName).append("()' was found on class: '");
                buffer.append(object.getClass().getName()).append("'.");
                throw new RuntimeException(buffer.toString(), e);
            }
        }
        return method;
    }

    /**
     * Invoke the getterMethod for the given source object.
     *
     * @param getterMethod the getter method to invoke
     * @param source the source object to invoke the getter method on
     * @param property the getter method property name (used for logging)
     * @param path the full expression path (used for logging)
     * @return the getter result
     */
    private static Object invokeGetter(Method getterMethod, Object source,
        String property, String path) {

        try {
            // Retrieve target object from getter
            return getterMethod.invoke(source, new Object[0]);

        } catch (Exception e) {
            // Log detailed error message of why getter failed
            HtmlStringBuffer buffer = new HtmlStringBuffer();
            logBasicDescription(buffer, source, path, property);
            buffer.append("Result: error occurred while trying to get");
            buffer.append(" instance of '");
            buffer.append(getterMethod.getReturnType().getName());
            buffer.append("' using method: '");
            buffer.append(getterMethod.getName()).append("()' of class '");
            buffer.append(source.getClass().getName()).append("'.");
            throw new RuntimeException(buffer.toString(), e);
        }
    }

    /**
     * Find the source object setter method for the given property.
     *
     * @param source the source object to find the setter method on
     * @param property the property which setter needs to be looked up
     * @param targetClass the setter parameter type
     * @param path the full expression path (used for logging purposes)
     * @return the setter method
     */
    private static Method findSetter(Object source,
        String property, Class<?> targetClass, String path) {
        Method method = null;

        // Find the setter for property
        String setterName = ClickUtils.toSetterName(property);

        Class<?> sourceClass = source.getClass();
        Class<?>[] classArgs = { targetClass };
        try {
            method = sourceClass.getMethod(setterName, classArgs);
        } catch (Exception e) {
            // Log detailed error message of why setter lookup failed
            HtmlStringBuffer buffer = new HtmlStringBuffer();
            logBasicDescription(buffer, source, path, property);
            buffer.append("Result: setter method '");
            buffer.append(setterName).append("(").append(targetClass.getName());
            buffer.append(")' was not found on class '");
            buffer.append(source.getClass().getName()).append("'.");
            throw new RuntimeException(buffer.toString(), e);
        }
        return method;
    }

    /**
     * Invoke the setter method for the given source and target object.
     *
     * @param setterMethod the setter method to invoke
     * @param source the source object to invoke the setter method on
     * @param target the target object to set
     * @param property the setter method property name (used for logging)
     * @param path the full expression path (used for logging)
     */
    private static void invokeSetter(Method setterMethod, Object source,
        Object target, String property, String path) {

        try {
            Object[] objectArgs = {target};
            setterMethod.invoke(source, objectArgs);

        } catch (Exception e) {
            // Log detailed error message of why setter failed
            HtmlStringBuffer buffer = new HtmlStringBuffer();
            logBasicDescription(buffer, source, path, property);
            buffer.append("Result: error occurred while trying to set an");
            buffer.append(" instance of '");
            buffer.append(target.getClass().getName()).append("' using method '");
            buffer.append(setterMethod.getName()).append("(");
            buffer.append(target.getClass());
            buffer.append(")' of class '").append(source.getClass()).append("'.");
            throw new RuntimeException(buffer.toString(), e);
        }
    }

    /**
     * Log a generic error message to the specified buffer for the given object,
     * path and property.
     *
     * @param buffer the buffer to append log message to
     * @param object the active object when the exception occurred
     * @param path the current expression path
     * @param property the current property being processed
     */
    private static void logBasicDescription(HtmlStringBuffer buffer, Object object,
        String path, String property) {
        buffer.append("Invoked ensureObjectPathNotNull");
        buffer.append(" for class: '").append(object.getClass().getName());
        buffer.append("', path: '").append(path).append("' and property: '");
        buffer.append(property).append("'. ");
    }

   /**
    * Populate the given map from the values of the specified fieldList. The
    * map's key/value pairs are populated from the fields name/value. The keys
    * of the map are matched against each field name. If a key matches a field
    * name, the value of the field will be copied to the map.
    *
    * @param fieldList the forms list of fields to obtain field values from
    * @param map the map to populate with field values
    */
    private static void copyFieldsToMap(List<Field> fieldList, Map<String, Object> map) {

        LogService logService = ClickUtils.getLogService();

        String objectClassname = map.getClass().getName();
        objectClassname =
            objectClassname.substring(objectClassname.lastIndexOf(".") + 1);

        for (Field field : fieldList) {

            // Check if the map contains the fields name. The fields name can
            // also be a path for example 'foo.bar'
            String fieldName = field.getName();
            if (map.containsKey(fieldName)) {

                map.put(fieldName, field.getValueObject());

                if (logService.isDebugEnabled()) {
                    String msg = "   Form -> " + objectClassname + "."
                         + fieldName + " : " + field.getValueObject();

                    logService.debug(msg);
                }
            }
        }
    }

    /**
     * Copy the map values to the specified fieldList. For every field in the
     * field list, a lookup is done in the map for a matching value. A match is
     * found if a field name matches against a key in the map. The matching
     * value is then copied to the field.
     *
     * @param map the map containing values to populate the fields with
     * @param fieldList the forms list of fields to be populated
     */
    private static void copyMapToFields(Map<String, Object> map, List<Field> fieldList) {

        LogService logService = ClickUtils.getLogService();

        String objectClassname = map.getClass().getName();
        objectClassname =
            objectClassname.substring(objectClassname.lastIndexOf(".") + 1);

        for (Field field : fieldList) {
            String fieldName = field.getName();

            // Check if the fieldName is contained in the map. For
            // example if a field has the name 'user.address', check if
            // 'user.address' is contained in the map.
            if (map.containsKey(fieldName)) {

                Object result = map.get(fieldName);

                field.setValueObject(result);

                if (logService.isDebugEnabled()) {
                    String msg = "   Form <- " + objectClassname + "."
                        + fieldName + " : " + result;
                    logService.debug(msg);
                }
            }
        }
    }

    /**
     * Add buttons for the given Container to the specified buttons list,
     * recursively including any Fields contained in child containers. The list
     * of returned buttons will exclude any <tt>Button</tt> or <tt>Label</tt>
     * fields.
     *
     * @param container the container to obtain the fields from
     * @param buttons the list of contained fields
     */
    private static void addButtons(final Container container, final List<Button> buttons) {
        for (Control control : container.getControls()) {

            if (control instanceof Container) {
                // Include buttons that are containers
                if (control instanceof Button) {
                    buttons.add((Button) control);
                }
                Container childContainer = (Container) control;
                addButtons(childContainer, buttons);

            } else if (control instanceof Button) {
                buttons.add((Button) control);
            }
        }
    }

    /**
     * Add fields for the given Container to the specified field list,
     * recursively including any Fields contained in child containers.
     *
     * @param container the container to obtain the fields from
     * @param fields the list of contained fields
     */
    private static void addFields(final Container container, final List<Field> fields) {
        for (Control control : container.getControls()) {

            if (control instanceof Container) {
                // Include fields that are containers
                if (control instanceof Field) {
                    fields.add((Field) control);
                }
                Container childContainer = (Container) control;
                addFields(childContainer, fields);

            } else if (control instanceof Field) {
                fields.add((Field) control);
            }
        }
    }

    /**
     * Add input fields (TextField, TextArea, Select, Radio, Checkbox etc.) for
     * the given Container to the specified field list, recursively including
     * any Fields contained in child containers. The list of returned fields
     * will exclude any <tt>Button</tt>, <tt>FieldSet</tt> and <tt>Label</tt>
     * fields.
     *
     * @param container the container to obtain the fields from
     * @param fields the list of contained fields
     */
    private static void addInputFields(final Container container, final List<Field> fields) {
        for (Control control : container.getControls()) {

            if (control instanceof Label || control instanceof Button) {
                // Skip buttons and labels
                continue;

            } else if (control instanceof Container) {
                // Include fields but skip fieldSets
                if (control instanceof Field && !(control instanceof FieldSet)) {
                    fields.add((Field) control);
                }
                Container childContainer = (Container) control;
                addInputFields(childContainer, fields);

            } else if (control instanceof Field) {
                fields.add((Field) control);
            }
        }
    }

    /**
     * Add hidden fields for the given Container to the specified field list,
     * recursively including any Fields contained in child containers. The list
     * of returned fields will exclude any <tt>Button</tt>, <tt>FieldSet</tt>
     * and <tt>Label</tt> fields.
     *
     * @param container the container to obtain the hidden fields from
     * @param fields the list of contained fields
     */
    private static void addHiddenFields(final Container container, final List<Field> fields) {
        for (Control control : container.getControls()) {

            if (control instanceof Label || control instanceof Button) {
                // Skip buttons and labels
                continue;

            } else if (control instanceof Container) {
                // Include fields but skip fieldSets
                if (control instanceof Field && !(control instanceof FieldSet)) {
                    Field field = (Field) control;
                    if (field.isHidden()) {
                        fields.add((Field) control);
                    }
                }

                Container childContainer = (Container) control;
                addHiddenFields(childContainer, fields);

            } else if (control instanceof Field) {
                Field field = (Field) control;
                if (field.isHidden()) {
                    fields.add((Field) control);
                }
            }
        }
    }

    /**
     * Add fields for the container to the specified field list, recursively
     * including any Fields contained in child containers. The list
     * of returned fields will exclude any <tt>Button</tt> and <tt>FieldSet</tt>
     * fields.
     *
     * @param container the container to obtain the fields from
     * @param fields the list of contained fields
     */
    private static void addFieldsAndLabels(final Container container, final List<Field> fields) {
        for (Control control : container.getControls()) {

            if (control instanceof Button) {
                // Skip buttons
                continue;

            } else if (control instanceof Container) {
                // Include fields but skip fieldSets
                if (control instanceof Field && !(control instanceof FieldSet)) {
                    fields.add((Field) control);
                }
                Container childContainer = (Container) control;
                addFieldsAndLabels(childContainer, fields);

            } else if (control instanceof Field) {
                fields.add((Field) control);
            }
        }
    }

    /**
     * Add all the Fields for the given Container to the specified map,
     * recursively including any Fields contained in child containers.
     * <p/>
     * The map's key / value pair will consist of the control name and instance.
     *
     * @param container the container to obtain the fields from
     * @param fields the map of contained fields
     */
    private static void addFields(final Container container, final Map<String, Field> fields) {
        for (Control control : container.getControls()) {

            if (control instanceof Container) {
                // Include fields that are containers
                if (control instanceof Field) {
                    fields.put(control.getName(), (Field) control);
                }
                Container childContainer = (Container) control;
                addFields(childContainer, fields);

            } else if (control instanceof Field) {
                fields.put(control.getName(), (Field) control);
            }
        }
    }

    /**
     * Add the list of container fields to the specified list of fields, which
     * are not valid, not hidden and not disabled.
     * <p/>
     * The list of returned invalid fields will exclude any <tt>Button</tt>
     * fields.
     *
     * @param container the container to obtain the fields from
     * @param fields the map of contained fields
     */
    private static void addErrorFields(final Container container, final List<Field> fields) {
        for (Control control : container.getControls()) {

            if (control instanceof Button) {
                // Skip buttons
                continue;

            } else if (control instanceof Container) {
                if (control instanceof Field) {
                    Field field = (Field) control;
                    if (!field.isValid()
                        && !field.isHidden()
                        && !field.isDisabled()) {

                        fields.add((Field) control);
                    }
                }
                Container childContainer = (Container) control;
                addErrorFields(childContainer, fields);

            } else if (control instanceof Field) {
                Field field = (Field) control;
                if (!field.isValid()
                    && !field.isHidden()
                    && !field.isDisabled()) {

                    fields.add((Field) control);
                }
            }
        }
    }

    /**
     * Log a warning that the parent of the given control will be set to
     * the specified container.
     *
     * @param container the parent container
     * @param control the control which parent is being reset
     * @param currentParent the control current parent
     */
    private static void logParentReset(Container container, Control control,
        Object currentParent) {
        HtmlStringBuffer message = new HtmlStringBuffer();

        message.append("Changed ");
        message.append(ClassUtils.getShortClassName(control.getClass()));
        String controlId = control.getId();
        if (controlId != null) {
            message.append("[");
            message.append(controlId);
            message.append("]");
        } else {
            message.append("#");
            message.append(control.hashCode());
        }
        message.append(" parent from ");

        if (currentParent instanceof Page) {
            message.append(ClassUtils.getShortClassName(currentParent.getClass()));

        } else if (currentParent instanceof Container) {
            Container parentContainer = (Container) currentParent;

            message.append(ClassUtils.getShortClassName(parentContainer.getClass()));
            String parentId = parentContainer.getId();
            if (parentId != null) {
                message.append("[");
                message.append(parentId);
                message.append("]");
            } else {
                message.append("#");
                message.append(parentContainer.hashCode());
            }
        }

        message.append(" to ");
        message.append(ClassUtils.getShortClassName(container.getClass()));
        String id = container.getId();
        if (id != null) {
            message.append("[");
            message.append(id);
            message.append("]");
        } else {
            message.append("#");
            message.append(container.hashCode());
        }

        ClickUtils.getLogService().warn(message);
    }
    
    /**
     * This class fix an error in ognl's conversion of double->BigDecimal. The 
     * default conversion uses BigDecimal(double), the fix is to use 
     * BigDecimal.valueOf(double)
     *
     */
    private static class FixBigDecimalTypeConverter extends DefaultTypeConverter {
        @SuppressWarnings("unchecked")
        @Override
        public Object convertValue(Map context, Object value, Class toType) {
            if (value != null && toType == BigDecimal.class) {
                return bigDecValue(value);
            }
            return OgnlOps.convertValue(value, toType);
        }

        /**
     * Convert the given value into a BigDecimal.
     *
     * @param value the object to convert into a BigDecimal
     * @return the converted BigDecimal value
     */
        private BigDecimal bigDecValue(Object value) {
            if (value == null) {
                return BigDecimal.valueOf(0L);
            }
            Class<?> c = value.getClass();
            if (c == BigDecimal.class) {
                return (BigDecimal) value;
            }
            if (c == BigInteger.class) {
                return new BigDecimal((BigInteger) value);
            }
            if (c == Boolean.class) {
                return BigDecimal.valueOf(((Boolean) value).booleanValue()? 1 : 0);
            }
            if (c == Character.class) {
                return BigDecimal.valueOf(((Character) value).charValue());
            }
            return new BigDecimal(value.toString().trim());
        }
    }
}
