/*
 * ICESOFT COMMERCIAL SOURCE CODE LICENSE V 1.1
 *
 * The contents of this file are subject to the ICEsoft Commercial Source
 * Code License Agreement V1.1 (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.icesoft.com/license/commercial-source-v1.1.html
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations under
 * the License.
 *
 * Copyright 2009-2015 ICEsoft Technologies Canada, Corp. All Rights Reserved.
 */
package com.icesoft.faces.facelets.component.table.richdatagrid;

import org.apache.commons.beanutils.PropertyUtils;

import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class RichDataBooleanRowProperty implements Serializable {

    protected Class clazz;
    private String property;

    public String getProperty() {
        return property;
    }

    private static String IS_GETTER_PREFIX = "is";
    private static String GET_GETTER_PREFIX = "get";
    private Method getter;

    public RichDataBooleanRowProperty(Class clazz, String property) {
        this.clazz = clazz;
        if (property != null && confirmEditableRowProperty(property) && (confirmIsGetter(property) || confirmGetGetter(property))) {
            this.property = property;
        }
    }

    protected Boolean callBooleanRowPropertyGetter(Object row) {
        try {
            return (Boolean) (getter.invoke(row, new Object[0]));
        } catch (IllegalAccessException iae) {
            throw new IllegalArgumentException(this.getClass().getSimpleName()
                    + " IllegalAccessException thrown calling editableRowProperty getter");
        } catch (InvocationTargetException ite) {
            throw new IllegalArgumentException(this.getClass().getSimpleName()
                    + " InvocationTargetException thrown calling editableRowProperty getter");
        }
    }

    private boolean confirmEditableRowProperty(String property) {
        boolean isConfirmed = false;
        PropertyDescriptor[] propertyDescs = PropertyUtils
                .getPropertyDescriptors(clazz);
        for (PropertyDescriptor propertyDesc : propertyDescs) {
            if (propertyDesc.getName().equals(property)) {
                isConfirmed = true;
                break;
            }
        }
        if (!isConfirmed) {
            throw new IllegalArgumentException(this.getClass().getSimpleName()
                    + " must be initialized with a valid property String");
        }
        return isConfirmed;
    }

    private boolean confirmIsGetter(String property) {
        String propertyCapitalized = Character.toUpperCase
                (property.charAt(0)) + property.substring(1);
        Class[] types = new Class[]{};
        String propertyMethodName = IS_GETTER_PREFIX + propertyCapitalized;
        try {
            getter = clazz.getMethod(propertyMethodName, types);
            return true;
        } catch (NoSuchMethodException nsme) {
            // try again with the other possible prefix on a boolean getter
            return false;
        }
    }

    private boolean confirmGetGetter(String property) {
        String propertyCapitalized = Character.toUpperCase
                (property.charAt(0)) + property.substring(1);
        Class[] types = new Class[]{};
        String propertyMethodName = GET_GETTER_PREFIX + propertyCapitalized;
        try {
            getter = clazz.getMethod(propertyMethodName, types);
            return true;
        } catch (NoSuchMethodException nsme) {
            // Did not find is* or get* method for this property
            throw new IllegalArgumentException(this.getClass().getSimpleName()
                    + " property getter not found");
        }
    }

}
