org.ajax4jsf.builder.config.ComponentBaseBean.java Source code

Java tutorial

Introduction

Here is the source code for org.ajax4jsf.builder.config.ComponentBaseBean.java

Source

/**
 * License Agreement.
 *
 * Rich Faces - Natural Ajax for Java Server Faces (JSF)
 *
 * Copyright (C) 2007 Exadel, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */

package org.ajax4jsf.builder.config;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.TreeMap;

import javax.faces.component.StateHolder;
import javax.faces.context.FacesContext;
import javax.naming.ConfigurationException;

import org.apache.commons.beanutils.PropertyUtils;

public class ComponentBaseBean extends JsfBean {

    private static final String[] ignorableComponentProperties = { "class", "attributes", "childCount", "children",
            "facets", "facetsAndChildren", "family", "parent", "rendererType", "rendersChildren", "submittedValue",
            "transient" };
    private static final String[] enabledTagProperties = { "binding" };
    private static final String[] attachedStateProperties = { "javax.faces.component.StateHolder", "java.util.List",
            "javax.faces.el.MethodBinding", "javax.faces.el.ValueBinding", "javax.el.MethodExpression",
            "javax.el.ValueExpression", "javax.faces.convert.Converter" };

    /**
     * JSP ( facelets ? ) tag description for component
     */
    private TagBean _tag;
    private TagHandlerBean _taghandler;
    /**
     * Descriptions of component JavaBean properties
     */
    private Map<String, PropertyBean> properties = new TreeMap<String, PropertyBean>();
    /**
     * Flag for generate component instance class
     */
    private boolean generate = true;

    /**
     * @return Returns the tag.
     */
    public TagBean getTag() {
        return _tag;
    }

    /**
     * @param tag The tag to set.
     */
    public void setTag(TagBean tag) {
        _tag = tag;
        tag.setParent(this);
    }

    /**
     * @return Returns the generate.
     */
    public boolean isGenerate() {
        return this.generate;
    }

    /**
     * @param generate The generate to set.
     */
    public void setGenerate(boolean generate) {
        this.generate = generate;
    }

    /**
     * @return Returns the tagSupport.
     */
    public TagHandlerBean getTaghandler() {
        return this._taghandler;
    }

    /**
     * @param tagSupport The tagSupport to set.
     */
    public void setTaghandler(TagHandlerBean tagSupport) {
        this._taghandler = tagSupport;
    }

    /**
     * @return Returns the properties.
     */
    public Collection<PropertyBean> getProperties() {
        return properties.values();
    }

    /**
     * @param name
     * @return true if component have property with given name
     */
    public boolean containProperty(String name) {
        return properties.containsKey(name);
    }

    public PropertyBean getProperty(String name) {
        return properties.get(name);
    }

    /**
     * Append property to component. If property with name exist, replace it
     * @param property
     */
    public void addProperty(PropertyBean property) {
        this.properties.put(property.getName(), property);
        property.setParent(this);
    }

    /**
     * Subclasses should extend this method to provide specifc checks
     * 
     * Check existing and default properties
     * For properties filled from configuration, attempt to set additional parameters.
     * If base class have any bean properties, append it to configured
     * @throws ConfigurationException 
     */
    public void checkProperties() throws ParsingException {
        try {
            getLog().debug("Parse properties for Component " + getName() + " with superclass " + getSuperclass());
            if (getSuperclass() != null) {
                Class<?> superClass = getLoader().loadClass(getSuperclass());

                new ClassWalkingLogic(superClass).walk(new ClassVisitor() {
                    public void visit(Class<?> clazz) {
                        checkPropertiesForClass(clazz);
                    }
                });
            }
        } catch (ClassNotFoundException e) {
            getLog().error("superclass not found for component " + getName(), e);
        }
        if (null != getTag()) {
            try {
                Class superClass = getLoader().loadClass(getTag().getSuperclass());
                PropertyDescriptor[] properties = PropertyUtils.getPropertyDescriptors(superClass);
                // for all properties, add it to component. If property have not abstract getter/setter ,
                // add it with exist = true . If property in list of hidden names, set hidden = true.
                for (int i = 0; i < properties.length; i++) {
                    PropertyDescriptor descriptor = properties[i];
                    Method writeMethod = descriptor.getWriteMethod();
                    if (containProperty(descriptor.getName())) {
                        if (null != writeMethod && !Modifier.isAbstract(writeMethod.getModifiers())
                                && Modifier.isPublic(writeMethod.getModifiers())) {
                            ((PropertyBean) this.properties.get(descriptor.getName())).setExistintag(true);
                        }
                    } else if (null != writeMethod && Modifier.isPublic(writeMethod.getModifiers())) {
                        if (Arrays.asList(enabledTagProperties).contains(descriptor.getName())) {
                            Class type = descriptor.getPropertyType();
                            getLog().debug("Register tag property  " + descriptor.getName() + " with type name "
                                    + type.getCanonicalName());
                            PropertyBean property = new PropertyBean();
                            property.setName(descriptor.getName());
                            property.setDescription(descriptor.getShortDescription());
                            property.setDisplayname(descriptor.getDisplayName());
                            property.setClassname(descriptor.getPropertyType().getCanonicalName());
                            property.setExist(true);
                            if (!Modifier.isAbstract(writeMethod.getModifiers())) {
                                property.setExistintag(true);
                            }
                            addProperty(property);
                        }
                    }
                }
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                getLog().error("superclass not found for tag " + getTag().getName(), e);
            }

        }
    }

    /**
     * @param superClass
     */
    private void checkPropertiesForClass(Class<?> superClass) {
        getLog().debug("Check properties for class " + superClass.getName());
        // get all property descriptors
        PropertyDescriptor[] properties = PropertyUtils.getPropertyDescriptors(superClass);
        // for all properties, add it to component. If property have not abstract getter/setter ,
        // add it with exist = true . If property in list of hidden names, set hidden = true.
        PropertyBean property;
        for (int i = 0; i < properties.length; i++) {
            PropertyDescriptor descriptor = properties[i];
            if (!containProperty(descriptor.getName())) {
                if (isIgnorableProperty(superClass, descriptor.getName())) {
                    continue;
                }
                Class<?> type = descriptor.getPropertyType();
                getLog().debug("Register property  " + descriptor.getName() + " with type name "
                        + type.getCanonicalName());
                property = new PropertyBean();
                property.setName(descriptor.getName());
                property.setDescription(descriptor.getShortDescription());
                property.setDisplayname(descriptor.getDisplayName());
                property.setClassname(descriptor.getPropertyType().getCanonicalName());
                property.setExist(true);
                addProperty(property);
            } else {
                // Load and check property.
                getLog().debug("Check  property  " + descriptor.getName());
                property = (PropertyBean) this.properties.get(descriptor.getName());
                if (property.getClassname() == null) {
                    property.setClassname(descriptor.getPropertyType().getCanonicalName());
                } else {
                    if (!property.getClassname().equals(descriptor.getPropertyType().getCanonicalName())) {
                        String message = "Class " + property.getClassname() + " for property " + property.getName()
                                + " not equals with real bean property type: "
                                + descriptor.getPropertyType().getCanonicalName();
                        getLog().error(message);
                        //throw new IllegalArgumentException(message);
                    }
                }
                if (property.getDescription() == null) {
                    property.setDescription(descriptor.getShortDescription());
                }
                if (property.getDisplayname() == null) {
                    property.setDisplayname(descriptor.getDisplayName());
                }
                property.setExist(true);
            }
            Method getter = descriptor.getReadMethod();
            Method setter = descriptor.getWriteMethod();
            // Abstract methods
            if (null != setter && null != getter) {
                if ((Modifier.isAbstract(getter.getModifiers()) && Modifier.isAbstract(setter.getModifiers()))
                        || superClass.isInterface()) {
                    getLog().debug("Detect as abstract property  " + descriptor.getName());
                    property.setExist(false);
                }
            }

            if (null == setter || (!Modifier.isPublic(setter.getModifiers()))) {
                getLog().debug("Detect as hidden property  " + descriptor.getName());
                property.setHidden(true);
            }
            if (isAttachedProperty(property)) {
                property.setAttachedstate(true);
            }
            if (property.isInstanceof("javax.faces.el.MethodBinding")
                    || property.isInstanceof("javax.faces.el.ValueBinding")) {
                property.setElonly(true);
            }

        }
    }

    private boolean isIgnorableProperty(Class<?> base, String name) {
        return Arrays.asList(ignorableComponentProperties).contains(name);
    }

    private boolean isAttachedProperty(PropertyBean prop) {
        for (int i = 0; i < attachedStateProperties.length; i++) {
            String clazz = attachedStateProperties[i];
            if (prop.isInstanceof(clazz)) {
                return true;
            }
        }
        return false;
    }

    public boolean isStateHolderRequired() {
        getLog().info("isStateHolderRequired");
        for (PropertyBean propertyBean : getProperties()) {
            getLog().info("Property " + propertyBean.getName() + "/" + propertyBean.isTransient());
            if (!propertyBean.isTransient()) {
                return true;
            }
        }
        return false;
    }

    public boolean isSuperclassImplementsStateHolder() {
        try {
            Class superClass = getLoader().loadClass(getSuperclass());
            return (StateHolder.class.isAssignableFrom(superClass));
        } catch (ClassNotFoundException e) {
            getLog().error("superclass not found for tag " + getTag().getName(), e);
            return false;
        }
    }

    public boolean isSuperSaveStateMethodExists() {
        try {
            Class superClass = getLoader().loadClass(getSuperclass());
            Class[] signature = { FacesContext.class };
            try {
                Method m = superClass.getMethod("saveState", signature);
                return !Modifier.isAbstract(m.getModifiers());
            } catch (NoSuchMethodException e) {
                return false;
            }
        } catch (ClassNotFoundException e) {
            getLog().error("superclass not found for tag " + getTag().getName(), e);
            return false;
        }
    }

    public boolean isSuperRestoreStateMethodExists() {
        try {
            Class superClass = getLoader().loadClass(getSuperclass());
            Class[] signature = { FacesContext.class, Object.class };
            try {
                Method m = superClass.getMethod("restoreState", signature);
                return !Modifier.isAbstract(m.getModifiers());
            } catch (NoSuchMethodException e) {
                return false;
            }
        } catch (ClassNotFoundException e) {
            getLog().error("superclass not found for tag " + getTag().getName(), e);
            return false;
        }
    }

    public boolean isSuperIsTransientMethodExists() {
        try {
            Class superClass = getLoader().loadClass(getSuperclass());
            Class[] signature = new Class[0];
            try {
                Method m = superClass.getMethod("isTransient", signature);
                return !Modifier.isAbstract(m.getModifiers());
            } catch (NoSuchMethodException e) {
                return false;
            }
        } catch (ClassNotFoundException e) {
            getLog().error("superclass not found for tag " + getTag().getName(), e);
            return false;
        }
    }

    public boolean isSuperSetTransientMethodExists() {
        try {
            Class superClass = getLoader().loadClass(getSuperclass());
            Class[] signature = { boolean.class };
            try {
                Method m = superClass.getMethod("setTransient", signature);
                return !Modifier.isAbstract(m.getModifiers());
            } catch (NoSuchMethodException e) {
                return false;
            }
        } catch (ClassNotFoundException e) {
            getLog().error("superclass not found for tag " + getTag().getName(), e);
            return false;
        }
    }
}